1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | /* Code example for the blog entry "Java Battle Royal: LinkedList vs ArrayList vs DynamicIntArray" "silly" linear search then insertion to prove a point. Java: Linked-list vs ArrayList vs DynamicIntArray. This code was an improved of David's (faulty) example (http://ideone.com/lmNDj) i.e. http://kjellkod.wordpress.com/2012/08/08/java-galore-linkedlist-vs-arraylist-vs-dynamicintarray/ */ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Random; import java.util.Vector; import java.io.IOException; public class Main { class DynamicIntArray { private int[] storage; private int size; private final int INITIAL_CAPACITY = 8; private final int GROW_FACTOR = 2; private void rangeCheck(int index){ if(index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); } // ref: http://www.algolist.net/Data_structures/Dynamic_array/Capacity_management private void ensureCapacity(int size_wanted) { int max_capacity = storage.length; if (size_wanted > max_capacity) { max_capacity = max_capacity * GROW_FACTOR +1; // http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#copyOf%28int[],%20int%29 storage = Arrays.copyOf(storage, max_capacity); // increases array size + copy contents } } public DynamicIntArray() { storage = new int[INITIAL_CAPACITY]; size = 0; } public int size() {return size;} public boolean equals(List<Integer> list) { boolean success = (list.size() == size()); if(success) { for(int idx = 0; success && (idx < size()); ++idx) { success = success && (get(idx) == list.get(idx).intValue()); } } return success; } public int get(int position){ rangeCheck(position); return storage[position]; } public void set(int index, int value){ rangeCheck(index); storage[index] = value; } public void add(int value) { insertAt(size, value); // same as c++ std::vector push_back } // Insert the value at the given index and shift 'tail' to give space. // The value can either be last position (size) or within the range 0 -> size. public void insertAt(int index, int value) { if(index < 0 || index > size) // allows for push_back to last index also throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); ensureCapacity(size+1); int move_count = size - index; // number of elements to shift if( move_count > 0) System.arraycopy(storage, index, storage, index+1, move_count); storage[index] = value; size++; } public void removeAt(int index) { rangeCheck(index); int move_count = size - index - 1; if (move_count > 0) System.arraycopy(storage, index + 1, storage, index, move_count); size--; } public void printAll() { for (int idx = 0; idx < size; idx++) System.out.printf(" [%d]=%d", idx, get(idx)); System.out.println(); } } // DynamicIntArray static class Result { int size; long linkedListTime; long arrayListTime; long dynamicArrayTime; public Result(int size) { this.size = size; } } public static void main(String[] args) throws Exception { Main obj = new Main(); // warm up code to make the benchmark more accurate for (int i = 0; i < 100; i++) obj.listVsVectorLinearPerformance(1000); // print the header System.out.printf("%-15s %-20s %-20s %-20s%n", "#Elements", "LinkedList", "ArrayList", "DynamicArray"); // perform the benchmarking printResult(obj.listVsVectorLinearPerformance(100)); printResult(obj.listVsVectorLinearPerformance(200)); printResult(obj.listVsVectorLinearPerformance(500)); printResult(obj.listVsVectorLinearPerformance(1000)); printResult(obj.listVsVectorLinearPerformance(2000)); printResult(obj.listVsVectorLinearPerformance(3000)); printResult(obj.listVsVectorLinearPerformance(4000)); printResult(obj.listVsVectorLinearPerformance(5000)); printResult(obj.listVsVectorLinearPerformance(10000)); // printResult(obj.listVsVectorLinearPerformance(20000)); // CPU time exceeded } private static void printResult(Result r) { long min = Math.min(r.linkedListTime, Math.min(r.arrayListTime, r.dynamicArrayTime)); System.out.printf("%-15d %-10d (%-3.0f%%) %-10d (%-3.0f%%) %-10d (%-3.0f%%)%n", r.size, r.linkedListTime, (100 * (double) r.linkedListTime) / min, r.arrayListTime, (100 * (double) r.arrayListTime) / min, r.dynamicArrayTime, (100 * (double) r.dynamicArrayTime) / min); } private Result listVsVectorLinearPerformance(int size) { Integer[] array = new Integer[size]; Random random = new Random(123456789L); LinkedList<Integer> linkedList = new LinkedList<Integer>(Arrays.asList(-1)); ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(-1)); DynamicIntArray dynamicArray = new DynamicIntArray(); dynamicArray.add(-1); for (int i = 0; i < array.length; i++) array[i] = random.nextInt(Integer.MAX_VALUE); Result result = new Result(size); long before = System.nanoTime(); linearInsertion(array, linkedList); result.linkedListTime = (System.nanoTime() - before) / 1000; before = System.nanoTime(); linearInsertion(array, arrayList); result.arrayListTime = (System.nanoTime() - before) / 1000; before = System.nanoTime(); linearInsertionToDynamicArray(array, dynamicArray); result.dynamicArrayTime = (System.nanoTime() - before) / 1000; // check that they are equal if (!(linkedList.equals(arrayList) && dynamicArray.equals(arrayList))) throw new RuntimeException("Not equal..."); return result; } private static void linearInsertion(Integer[] intArray, LinkedList<Integer> list) { for (Integer integer : intArray) { for (ListIterator<Integer> it = list.listIterator(); it.hasNext();) { if (integer.compareTo(it.next()) >= 0) { it.previous(); // should be added before element it.add(integer); break; } } } } // 1. Avoid calling size() a lot makes actually a big difference // 2. NEVER use iterators to loop through and ArrayList. Random access is so much faster // ref: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/RandomAccess.html private static void linearInsertion(Integer[] intArray, ArrayList<Integer> list) { for (Integer integer : intArray) { int list_size = list.size(); // on purpose: it is smarter to avoid calling size() every loop for (int i = 0; i < list_size; i++) { if (integer.compareTo(list.get(i)) >= 0) { list.add(i, integer); break; } } } } private static void linearInsertionToDynamicArray(Integer[] numbers, DynamicIntArray array) { for(Integer integer : numbers){ int value = integer.intValue(); // int array_size = array.size(); // on purpose: even faster would be to avoid calling size() every loop for(int idx = 0; idx < array.size(); idx++){ if(value >= array.get(idx)){ array.insertAt(idx, value); break; } } } } } |
LyoKQ29kZSBleGFtcGxlIGZvciB0aGUgYmxvZyBlbnRyeSAKIkphdmEgQmF0dGxlIFJveWFsOiBMaW5rZWRMaXN0IHZzIEFycmF5TGlzdCB2cyBEeW5hbWljSW50QXJyYXkiCgoic2lsbHkiIGxpbmVhciBzZWFyY2ggdGhlbiBpbnNlcnRpb24gdG8gcHJvdmUgYSBwb2ludC4gCkphdmE6IExpbmtlZC1saXN0IHZzIEFycmF5TGlzdCB2cyBEeW5hbWljSW50QXJyYXkuIFRoaXMgY29kZSB3YXMgYW4gaW1wcm92ZWQgb2YgRGF2aWQncyAoZmF1bHR5KSBleGFtcGxlIChodHRwOi8vaWRlb25lLmNvbS9sbU5EaikKCmkuZS4gaHR0cDovL2tqZWxsa29kLndvcmRwcmVzcy5jb20vMjAxMi8wOC8wOC9qYXZhLWdhbG9yZS1saW5rZWRsaXN0LXZzLWFycmF5bGlzdC12cy1keW5hbWljaW50YXJyYXkvCiovCgoKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlzOwppbXBvcnQgamF2YS51dGlsLkxpbmtlZExpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5MaXN0SXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuUmFuZG9tOwppbXBvcnQgamF2YS51dGlsLlZlY3RvcjsKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247ICAgCgpwdWJsaWMgY2xhc3MgTWFpbiB7CgoKCmNsYXNzIER5bmFtaWNJbnRBcnJheSB7CgogIHByaXZhdGUgaW50W10gc3RvcmFnZTsKICBwcml2YXRlIGludCBzaXplOwogIHByaXZhdGUgZmluYWwgIGludCBJTklUSUFMX0NBUEFDSVRZID0gODsKICBwcml2YXRlIGZpbmFsIGludCBHUk9XX0ZBQ1RPUiA9IDI7CiAKICBwcml2YXRlIHZvaWQgcmFuZ2VDaGVjayhpbnQgaW5kZXgpewogICAgaWYoaW5kZXggPCAwIHx8IGluZGV4ID49IHNpemUpIAogICAgICB0aHJvdyBuZXcgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbigiSW5kZXg6ICIgKyBpbmRleCArICIsIFNpemU6ICIgKyBzaXplKTsKICB9ICAKCiAgLy8gcmVmOiBodHRwOi8vd3d3LmFsZ29saXN0Lm5ldC9EYXRhX3N0cnVjdHVyZXMvRHluYW1pY19hcnJheS9DYXBhY2l0eV9tYW5hZ2VtZW50CiAgcHJpdmF0ZSB2b2lkIGVuc3VyZUNhcGFjaXR5KGludCBzaXplX3dhbnRlZCkgewogICAgaW50IG1heF9jYXBhY2l0eSA9IHN0b3JhZ2UubGVuZ3RoOwogICAgaWYgKHNpemVfd2FudGVkID4gbWF4X2NhcGFjaXR5KSB7CiAgICAgIG1heF9jYXBhY2l0eSA9IG1heF9jYXBhY2l0eSAqIEdST1dfRkFDVE9SICsxOyAKICAgICAgLy8gaHR0cDovL2RvY3Mub3JhY2xlLmNvbS9qYXZhc2UvNi9kb2NzL2FwaS9qYXZhL3V0aWwvQXJyYXlzLmh0bWwjY29weU9mJTI4aW50W10sJTIwaW50JTI5CiAgICAgIHN0b3JhZ2UgPSBBcnJheXMuY29weU9mKHN0b3JhZ2UsIG1heF9jYXBhY2l0eSk7IC8vIGluY3JlYXNlcyBhcnJheSBzaXplICsgY29weSBjb250ZW50cwogICAgfSAKIH0KCgogcHVibGljIER5bmFtaWNJbnRBcnJheSgpIHsKICAgIHN0b3JhZ2UgPSBuZXcgaW50W0lOSVRJQUxfQ0FQQUNJVFldOyAKICAgIHNpemUgPSAwOwogIH0KICAgcHVibGljIGludCBzaXplKCkge3JldHVybiBzaXplO30KCiAgIHB1YmxpYyBib29sZWFuIGVxdWFscyhMaXN0PEludGVnZXI+IGxpc3QpCiAgIHsKICAgICBib29sZWFuIHN1Y2Nlc3MgPSAobGlzdC5zaXplKCkgPT0gc2l6ZSgpKTsKICAgICBpZihzdWNjZXNzKSB7CiAgICAgICBmb3IoaW50IGlkeCA9IDA7IHN1Y2Nlc3MgJiYgKGlkeCA8IHNpemUoKSk7ICsraWR4KSB7CiAgICAgICAgIHN1Y2Nlc3MgPSBzdWNjZXNzICYmIChnZXQoaWR4KSA9PSBsaXN0LmdldChpZHgpLmludFZhbHVlKCkpOwogICAgICAgfQogICAgIH0KICAgICByZXR1cm4gc3VjY2VzczsKICAgfSAKCgogICAgcHVibGljIGludCBnZXQoaW50IHBvc2l0aW9uKXsKICAgIHJhbmdlQ2hlY2socG9zaXRpb24pOwogICAgcmV0dXJuIHN0b3JhZ2VbcG9zaXRpb25dOwogIH0KCiAgICBwdWJsaWMgdm9pZCBzZXQoaW50IGluZGV4LCBpbnQgdmFsdWUpewogICAgICByYW5nZUNoZWNrKGluZGV4KTsKICAgICAgc3RvcmFnZVtpbmRleF0gPSB2YWx1ZTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCBhZGQoaW50IHZhbHVlKSB7IAogICAgICBpbnNlcnRBdChzaXplLCB2YWx1ZSk7ICAvLyBzYW1lIGFzIGMrKyBzdGQ6OnZlY3RvciBwdXNoX2JhY2sKICAgIH0KCgogICAgLy8gSW5zZXJ0IHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4gaW5kZXggYW5kIHNoaWZ0ICd0YWlsJyB0byBnaXZlIHNwYWNlLgogICAgLy8gVGhlIHZhbHVlIGNhbiBlaXRoZXIgYmUgbGFzdCBwb3NpdGlvbiAoc2l6ZSkgb3Igd2l0aGluIHRoZSByYW5nZSAwIC0+IHNpemUuCiAgICBwdWJsaWMgdm9pZCBpbnNlcnRBdChpbnQgaW5kZXgsIGludCB2YWx1ZSkgewogICAgICBpZihpbmRleCA8IDAgfHwgaW5kZXggPiBzaXplKSAgICAvLyBhbGxvd3MgZm9yIHB1c2hfYmFjayB0byBsYXN0IGluZGV4IGFsc28KICAgICAgICB0aHJvdyBuZXcgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbigiSW5kZXg6ICIgKyBpbmRleCArICIsIFNpemU6ICIgKyBzaXplKTsKICAgCiAgICAgIGVuc3VyZUNhcGFjaXR5KHNpemUrMSk7CiAgICAgIGludCBtb3ZlX2NvdW50ID0gc2l6ZSAtIGluZGV4OyAJCQkJCS8vIG51bWJlciBvZiBlbGVtZW50cyB0byBzaGlmdAogICAgICBpZiggbW92ZV9jb3VudCA+IDApIAkJCQkJCiAgICAgICAgU3lzdGVtLmFycmF5Y29weShzdG9yYWdlLCBpbmRleCwgc3RvcmFnZSwgaW5kZXgrMSwgbW92ZV9jb3VudCk7CiAgICAgICAgCiAgICAgICBzdG9yYWdlW2luZGV4XSA9IHZhbHVlOwogICAgICAgc2l6ZSsrOwogICAgfQoKICAgICAgcHVibGljIHZvaWQgcmVtb3ZlQXQoaW50IGluZGV4KSB7CiAgICAgICAgcmFuZ2VDaGVjayhpbmRleCk7CiAgICAgICAgaW50IG1vdmVfY291bnQgPSBzaXplIC0gaW5kZXggLSAxOwogICAgICAgaWYgKG1vdmVfY291bnQgPiAwKQogICAgICAgICAgU3lzdGVtLmFycmF5Y29weShzdG9yYWdlLCBpbmRleCArIDEsIHN0b3JhZ2UsIGluZGV4LCBtb3ZlX2NvdW50KTsKCiAgICAgICBzaXplLS07CiAgICAgIH0KCgogICAgcHVibGljIHZvaWQgcHJpbnRBbGwoKSB7CiAgICAgIGZvciAoaW50IGlkeCA9IDA7IGlkeCA8IHNpemU7IGlkeCsrKQogICAgICAgIFN5c3RlbS5vdXQucHJpbnRmKCIgIFslZF09JWQiLCBpZHgsIGdldChpZHgpKTsKICAgICAgIAogICAgICBTeXN0ZW0ub3V0LnByaW50bG4oKTsKICAgfQp9IC8vIER5bmFtaWNJbnRBcnJheQoKCgoKCXN0YXRpYyBjbGFzcyBSZXN1bHQgewoJCWludCBzaXplOwoJCWxvbmcgbGlua2VkTGlzdFRpbWU7CgkJbG9uZyBhcnJheUxpc3RUaW1lOwoJCWxvbmcgZHluYW1pY0FycmF5VGltZTsKCQkKCQlwdWJsaWMgUmVzdWx0KGludCBzaXplKSB7CgkJCXRoaXMuc2l6ZSA9IHNpemU7CgkJfQoJfQoJCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBNYWluIG9iaiA9IG5ldyBNYWluKCk7CgoJCS8vIHdhcm0gdXAgY29kZSB0byBtYWtlIHRoZSBiZW5jaG1hcmsgbW9yZSBhY2N1cmF0ZQoJCWZvciAoaW50IGkgPSAwOyBpIDwgMTAwOyBpKyspCgkJCW9iai5saXN0VnNWZWN0b3JMaW5lYXJQZXJmb3JtYW5jZSgxMDAwKTsKCgkJLy8gcHJpbnQgdGhlIGhlYWRlcgoJCVN5c3RlbS5vdXQucHJpbnRmKCIlLTE1cyAlLTIwcyAlLTIwcyAlLTIwcyVuIiwgCgkJCQkJCSAgIiNFbGVtZW50cyIsICAiTGlua2VkTGlzdCIsICJBcnJheUxpc3QiLCAiRHluYW1pY0FycmF5Iik7CgoJCS8vIHBlcmZvcm0gdGhlIGJlbmNobWFya2luZwoJCXByaW50UmVzdWx0KG9iai5saXN0VnNWZWN0b3JMaW5lYXJQZXJmb3JtYW5jZSgxMDApKTsKCQlwcmludFJlc3VsdChvYmoubGlzdFZzVmVjdG9yTGluZWFyUGVyZm9ybWFuY2UoMjAwKSk7CgkJcHJpbnRSZXN1bHQob2JqLmxpc3RWc1ZlY3RvckxpbmVhclBlcmZvcm1hbmNlKDUwMCkpOwoJCXByaW50UmVzdWx0KG9iai5saXN0VnNWZWN0b3JMaW5lYXJQZXJmb3JtYW5jZSgxMDAwKSk7CgkJcHJpbnRSZXN1bHQob2JqLmxpc3RWc1ZlY3RvckxpbmVhclBlcmZvcm1hbmNlKDIwMDApKTsKCQlwcmludFJlc3VsdChvYmoubGlzdFZzVmVjdG9yTGluZWFyUGVyZm9ybWFuY2UoMzAwMCkpOwoJCXByaW50UmVzdWx0KG9iai5saXN0VnNWZWN0b3JMaW5lYXJQZXJmb3JtYW5jZSg0MDAwKSk7CgkJcHJpbnRSZXN1bHQob2JqLmxpc3RWc1ZlY3RvckxpbmVhclBlcmZvcm1hbmNlKDUwMDApKTsKCQlwcmludFJlc3VsdChvYmoubGlzdFZzVmVjdG9yTGluZWFyUGVyZm9ybWFuY2UoMTAwMDApKTsKICAgICAgICAgICAgICAgIC8vICAgICAgICAgIHByaW50UmVzdWx0KG9iai5saXN0VnNWZWN0b3JMaW5lYXJQZXJmb3JtYW5jZSgyMDAwMCkpOyAvLyBDUFUgdGltZSBleGNlZWRlZAoKCgl9CgoJcHJpdmF0ZSBzdGF0aWMgdm9pZCBwcmludFJlc3VsdChSZXN1bHQgcikgewoJCQoJCWxvbmcgbWluID0gTWF0aC5taW4oci5saW5rZWRMaXN0VGltZSwgTWF0aC5taW4oci5hcnJheUxpc3RUaW1lLCByLmR5bmFtaWNBcnJheVRpbWUpKTsKCQkKCQlTeXN0ZW0ub3V0LnByaW50ZigiJS0xNWQgJS0xMGQgKCUtMy4wZiUlKSAgICAlLTEwZCAoJS0zLjBmJSUpICAgICUtMTBkICglLTMuMGYlJSklbiIsIAoJCQkJci5zaXplLCAKCQkJCXIubGlua2VkTGlzdFRpbWUsICgxMDAgKiAoZG91YmxlKSByLmxpbmtlZExpc3RUaW1lKSAvIG1pbiwKCQkJCXIuYXJyYXlMaXN0VGltZSwgICgxMDAgKiAoZG91YmxlKSByLmFycmF5TGlzdFRpbWUpIC8gbWluLAoJCQkJci5keW5hbWljQXJyYXlUaW1lLCAgICAgKDEwMCAqIChkb3VibGUpIHIuZHluYW1pY0FycmF5VGltZSkgLyBtaW4pOwoJfQoKCXByaXZhdGUgUmVzdWx0IGxpc3RWc1ZlY3RvckxpbmVhclBlcmZvcm1hbmNlKGludCBzaXplKSB7CgoJCUludGVnZXJbXSBhcnJheSA9IG5ldyBJbnRlZ2VyW3NpemVdOwoJCVJhbmRvbSByYW5kb20gPSBuZXcgUmFuZG9tKDEyMzQ1Njc4OUwpOwoJCQoJCUxpbmtlZExpc3Q8SW50ZWdlcj4gbGlua2VkTGlzdCA9IG5ldyBMaW5rZWRMaXN0PEludGVnZXI+KEFycmF5cy5hc0xpc3QoLTEpKTsKCQlBcnJheUxpc3Q8SW50ZWdlcj4gYXJyYXlMaXN0ID0gbmV3IEFycmF5TGlzdDxJbnRlZ2VyPihBcnJheXMuYXNMaXN0KC0xKSk7CgkJRHluYW1pY0ludEFycmF5ICBkeW5hbWljQXJyYXkgPSBuZXcgRHluYW1pY0ludEFycmF5KCk7CiAgICAgICAgICAgICAgICBkeW5hbWljQXJyYXkuYWRkKC0xKTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykgCgkJCWFycmF5W2ldID0gcmFuZG9tLm5leHRJbnQoSW50ZWdlci5NQVhfVkFMVUUpOwoKCQlSZXN1bHQgcmVzdWx0ID0gbmV3IFJlc3VsdChzaXplKTsKCQkKCQlsb25nIGJlZm9yZSA9IFN5c3RlbS5uYW5vVGltZSgpOwoJCWxpbmVhckluc2VydGlvbihhcnJheSwgbGlua2VkTGlzdCk7CgkJcmVzdWx0LmxpbmtlZExpc3RUaW1lID0gKFN5c3RlbS5uYW5vVGltZSgpIC0gYmVmb3JlKSAvIDEwMDA7CgoJCWJlZm9yZSA9IFN5c3RlbS5uYW5vVGltZSgpOwoJCWxpbmVhckluc2VydGlvbihhcnJheSwgYXJyYXlMaXN0KTsKCQlyZXN1bHQuYXJyYXlMaXN0VGltZSA9IChTeXN0ZW0ubmFub1RpbWUoKSAtIGJlZm9yZSkgLyAxMDAwOwoKCQliZWZvcmUgPSBTeXN0ZW0ubmFub1RpbWUoKTsKCQlsaW5lYXJJbnNlcnRpb25Ub0R5bmFtaWNBcnJheShhcnJheSwgZHluYW1pY0FycmF5KTsKCQlyZXN1bHQuZHluYW1pY0FycmF5VGltZSA9IChTeXN0ZW0ubmFub1RpbWUoKSAtIGJlZm9yZSkgLyAxMDAwOwoKICAgICAgICAgICAgICAgIAoJCS8vIGNoZWNrIHRoYXQgdGhleSBhcmUgZXF1YWwKCQlpZiAoIShsaW5rZWRMaXN0LmVxdWFscyhhcnJheUxpc3QpICYmIGR5bmFtaWNBcnJheS5lcXVhbHMoYXJyYXlMaXN0KSkpCgkJCXRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCJOb3QgZXF1YWwuLi4iKTsKCQkKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXByaXZhdGUgc3RhdGljIHZvaWQgbGluZWFySW5zZXJ0aW9uKEludGVnZXJbXSBpbnRBcnJheSwgTGlua2VkTGlzdDxJbnRlZ2VyPiBsaXN0KSB7CgkJZm9yIChJbnRlZ2VyIGludGVnZXIgOiBpbnRBcnJheSkgewoJCQlmb3IgKExpc3RJdGVyYXRvcjxJbnRlZ2VyPiBpdCA9IGxpc3QubGlzdEl0ZXJhdG9yKCk7IGl0Lmhhc05leHQoKTspIHsKCQkJCWlmIChpbnRlZ2VyLmNvbXBhcmVUbyhpdC5uZXh0KCkpID49IDApIHsKCQkJCQlpdC5wcmV2aW91cygpOyAvLyBzaG91bGQgYmUgYWRkZWQgYmVmb3JlIGVsZW1lbnQKCQkJCQlpdC5hZGQoaW50ZWdlcik7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCX0KCQl9Cgl9CgogICAgICAgIC8vIDEuIEF2b2lkIGNhbGxpbmcgc2l6ZSgpIGEgbG90IG1ha2VzIGFjdHVhbGx5IGEgYmlnIGRpZmZlcmVuY2UKICAgICAgICAvLyAyLiBORVZFUiB1c2UgaXRlcmF0b3JzIHRvIGxvb3AgdGhyb3VnaCBhbmQgQXJyYXlMaXN0LiBSYW5kb20gYWNjZXNzIGlzIHNvIG11Y2ggZmFzdGVyIAogICAgICAgIC8vICAgIHJlZjogaHR0cDovL2RvY3Mub3JhY2xlLmNvbS9qYXZhc2UvMS40LjIvZG9jcy9hcGkvamF2YS91dGlsL1JhbmRvbUFjY2Vzcy5odG1sCglwcml2YXRlIHN0YXRpYyB2b2lkIGxpbmVhckluc2VydGlvbihJbnRlZ2VyW10gaW50QXJyYXksIEFycmF5TGlzdDxJbnRlZ2VyPiBsaXN0KSB7CiAJCWZvciAoSW50ZWdlciBpbnRlZ2VyIDogaW50QXJyYXkpIHsgCiAgICAgICAgICAgICAgICAgICAgICAgIGludCBsaXN0X3NpemUgPSBsaXN0LnNpemUoKTsgIC8vIG9uIHB1cnBvc2U6IGl0IGlzIHNtYXJ0ZXIgdG8gYXZvaWQgY2FsbGluZyBzaXplKCkgZXZlcnkgbG9vcAoJCQlmb3IgKGludCBpID0gMDsgaSA8IGxpc3Rfc2l6ZTsgaSsrKSB7CgkJCQlpZiAoaW50ZWdlci5jb21wYXJlVG8obGlzdC5nZXQoaSkpID49IDApIHsKCQkJCQlsaXN0LmFkZChpLCBpbnRlZ2VyKTsKCQkJCQlicmVhazsKCQkJCX0KCQkJfQoJCX0KCX0KCiAgIHByaXZhdGUgc3RhdGljIHZvaWQgbGluZWFySW5zZXJ0aW9uVG9EeW5hbWljQXJyYXkoSW50ZWdlcltdIG51bWJlcnMsIER5bmFtaWNJbnRBcnJheSBhcnJheSkgewogICAgICBmb3IoSW50ZWdlciBpbnRlZ2VyIDogbnVtYmVycyl7CiAgICAgICAgaW50IHZhbHVlID0gaW50ZWdlci5pbnRWYWx1ZSgpOyAgIAogICAgICAgICAvLyAgICAgICAgaW50IGFycmF5X3NpemUgPSBhcnJheS5zaXplKCk7ICAgICAgICAgICAvLyBvbiBwdXJwb3NlOiBldmVuIGZhc3RlciB3b3VsZCBiZSB0byBhdm9pZCBjYWxsaW5nIHNpemUoKSBldmVyeSBsb29wCiAgICAgICAgZm9yKGludCBpZHggPSAwOyBpZHggPCBhcnJheS5zaXplKCk7IGlkeCsrKXsgICAKICAgICAgICAgIGlmKHZhbHVlID49IGFycmF5LmdldChpZHgpKXsKICAgICAgICAgICAgYXJyYXkuaW5zZXJ0QXQoaWR4LCB2YWx1ZSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQoKfSAg
-
upload with new input
-
result: Success time: 2.78s memory: 245824 kB returned value: 0
#Elements LinkedList ArrayList DynamicArray 100 47 (188%) 38 (152%) 25 (100%) 200 174 (205%) 131 (154%) 85 (100%) 500 1028 (202%) 687 (135%) 508 (100%) 1000 4265 (206%) 2809 (135%) 2074 (100%) 2000 18636 (192%) 10953 (113%) 9682 (100%) 3000 45004 (208%) 26153 (121%) 21629 (100%) 4000 84825 (220%) 47616 (123%) 38570 (100%) 5000 145549 (254%) 75270 (132%) 57201 (100%) 10000 631982 (260%) 315272 (130%) 243037 (100%)
-
result: Success time: 2.83s memory: 245824 kB returned value: 0
#Elements LinkedList ArrayList DynamicArray 100 48 (171%) 38 (136%) 28 (100%) 200 176 (205%) 122 (142%) 86 (100%) 500 1072 (204%) 732 (139%) 525 (100%) 1000 3984 (189%) 2599 (124%) 2103 (100%) 2000 21723 (267%) 12362 (152%) 8145 (100%) 3000 50835 (241%) 25828 (122%) 21118 (100%) 4000 84710 (215%) 46630 (118%) 39355 (100%) 5000 139165 (243%) 74446 (130%) 57170 (100%) 10000 637223 (256%) 319725 (128%) 249114 (100%)
-
result: Success time: 8.23s memory: 245824 kB returned value: 0
#Elements LinkedList ArrayList DynamicArray 100 47 (157%) 39 (130%) 30 (100%) 200 177 (197%) 128 (142%) 90 (100%) 500 1074 (205%) 802 (153%) 524 (100%) 1000 4527 (233%) 2756 (142%) 1946 (100%) 2000 21782 (259%) 10873 (129%) 8405 (100%) 3000 49707 (232%) 26284 (122%) 21468 (100%) 4000 91929 (238%) 46914 (121%) 38652 (100%) 5000 141390 (246%) 75871 (132%) 57452 (100%) 10000 628813 (258%) 317474 (130%) 243352 (100%) 20000 3125540 (322%) 1319927 (136%) 971471 (100%)


