PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/de/jungblut/datastructure/ArrayUtils.java

http://github.com/thomasjungblut/thomasjungblut-common
Java | 1503 lines | 851 code | 140 blank | 512 comment | 176 complexity | 4121668c0e4bb95440990fcf96348e41 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. package de.jungblut.datastructure;
  2. import gnu.trove.list.array.TIntArrayList;
  3. import gnu.trove.set.hash.TIntHashSet;
  4. import java.lang.reflect.Array;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.HashSet;
  8. import java.util.List;
  9. import java.util.Random;
  10. import com.google.common.base.Preconditions;
  11. /**
  12. * Array utils for stuff that isn't included in {@link Arrays}.
  13. *
  14. * @author thomas.jungblut
  15. *
  16. */
  17. public final class ArrayUtils {
  18. private ArrayUtils() {
  19. throw new IllegalAccessError();
  20. }
  21. /**
  22. * Finds the occurence of the given key in the given array. Linear search,
  23. * worst case running time is O(n).
  24. *
  25. * @param array the array to search.
  26. * @param key the key to search.
  27. * @return -1 if the key wasn't found nowhere, or the index where the key was
  28. * found.
  29. */
  30. public static <T> int find(T[] array, T key) {
  31. Preconditions.checkNotNull(key);
  32. int position = -1;
  33. for (int i = 0; i < array.length; i++) {
  34. if (array[i].equals(key)) {
  35. position = i;
  36. break;
  37. }
  38. }
  39. return position;
  40. }
  41. /**
  42. * Finds the occurence of the given key in the given array. Linear search,
  43. * worst case running time is O(n).
  44. *
  45. * @param array the array to search.
  46. * @param key the key to search.
  47. * @return -1 if the key wasn't found nowhere, or the index where the key was
  48. * found.
  49. */
  50. public static int find(int[] array, int key) {
  51. Preconditions.checkNotNull(key);
  52. int position = -1;
  53. for (int i = 0; i < array.length; i++) {
  54. if (array[i] == key) {
  55. position = i;
  56. break;
  57. }
  58. }
  59. return position;
  60. }
  61. /**
  62. * Finds the occurence of the given key in the given array. Linear search,
  63. * worst case running time is O(n).
  64. *
  65. * @param array the array to search.
  66. * @param key the key to search.
  67. * @return -1 if the key wasn't found nowhere, or the index where the key was
  68. * found.
  69. */
  70. public static int find(long[] array, long key) {
  71. Preconditions.checkNotNull(key);
  72. int position = -1;
  73. for (int i = 0; i < array.length; i++) {
  74. if (array[i] == key) {
  75. position = i;
  76. break;
  77. }
  78. }
  79. return position;
  80. }
  81. /**
  82. * Concats the given arrays.
  83. *
  84. * @param arrays the arrays to pass.
  85. * @return a single array where the given arrays content is concatenated.
  86. */
  87. public static int[] concat(int[]... arrays) {
  88. int length = 0;
  89. for (int[] array1 : arrays)
  90. length += array1.length;
  91. int[] merged = new int[length];
  92. int index = 0;
  93. for (int[] array : arrays) {
  94. System.arraycopy(array, 0, merged, index, array.length);
  95. index += array.length;
  96. }
  97. return merged;
  98. }
  99. /**
  100. * Concats the given arrays.
  101. *
  102. * @param arrays the arrays to pass.
  103. * @return a single array where the given arrays content is concatenated.
  104. */
  105. public static long[] concat(long[]... arrays) {
  106. int length = 0;
  107. for (long[] array1 : arrays)
  108. length += array1.length;
  109. long[] merged = new long[length];
  110. int index = 0;
  111. for (long[] array : arrays) {
  112. System.arraycopy(array, 0, merged, index, array.length);
  113. index += array.length;
  114. }
  115. return merged;
  116. }
  117. /**
  118. * Concats the given arrays.
  119. *
  120. * @param arrays the arrays to pass.
  121. * @return a single array where the given arrays content is concatenated.
  122. */
  123. public static double[] concat(double[]... arrays) {
  124. int length = 0;
  125. for (double[] array1 : arrays)
  126. length += array1.length;
  127. double[] merged = new double[length];
  128. int index = 0;
  129. for (double[] array : arrays) {
  130. System.arraycopy(array, 0, merged, index, array.length);
  131. index += array.length;
  132. }
  133. return merged;
  134. }
  135. /**
  136. * Concats the given arrays.
  137. *
  138. * @param arrays the arrays to pass.
  139. * @return a single array where the given arrays content is concatenated.
  140. */
  141. @SuppressWarnings("unchecked")
  142. public static <T> T[] concat(T[]... arrays) {
  143. if (arrays.length > 0) {
  144. int length = 0;
  145. for (T[] array1 : arrays)
  146. length += array1.length;
  147. T[] merged = (T[]) Array.newInstance(arrays[0].getClass()
  148. .getComponentType(), length);
  149. int index = 0;
  150. for (T[] array : arrays) {
  151. System.arraycopy(array, 0, merged, index, array.length);
  152. index += array.length;
  153. }
  154. return merged;
  155. } else {
  156. return null;
  157. }
  158. }
  159. /**
  160. * Copies the given array into a new one.
  161. */
  162. public static int[] copy(int[] array) {
  163. int[] newInt = new int[array.length];
  164. System.arraycopy(array, 0, newInt, 0, array.length);
  165. return newInt;
  166. }
  167. /**
  168. * Copies the given array into a new one.
  169. */
  170. public static double[] copy(double[] array) {
  171. double[] newInt = new double[array.length];
  172. System.arraycopy(array, 0, newInt, 0, array.length);
  173. return newInt;
  174. }
  175. /**
  176. * Copies the given array into a new one.
  177. */
  178. public static long[] copy(long[] array) {
  179. long[] newInt = new long[array.length];
  180. System.arraycopy(array, 0, newInt, 0, array.length);
  181. return newInt;
  182. }
  183. /**
  184. * Copies the given array into a new one.
  185. */
  186. public static <T> T[] copy(T[] array) {
  187. return Arrays.copyOf(array, array.length);
  188. }
  189. /**
  190. * Swaps the given index x with y in the array.
  191. */
  192. public static void swap(int[] array, int x, int y) {
  193. int tmpIndex = array[x];
  194. array[x] = array[y];
  195. array[y] = tmpIndex;
  196. }
  197. /**
  198. * Swaps the given index x with y in the array.
  199. */
  200. public static void swap(long[] array, int x, int y) {
  201. long tmpIndex = array[x];
  202. array[x] = array[y];
  203. array[y] = tmpIndex;
  204. }
  205. /**
  206. * Swaps the given index x with y in the array.
  207. */
  208. public static void swap(double[] array, int x, int y) {
  209. double tmpIndex = array[x];
  210. array[x] = array[y];
  211. array[y] = tmpIndex;
  212. }
  213. /**
  214. * Swaps the given index x with y in the array.
  215. */
  216. public static void swap(boolean[] array, int x, int y) {
  217. boolean tmpIndex = array[x];
  218. array[x] = array[y];
  219. array[y] = tmpIndex;
  220. }
  221. /**
  222. * Swaps the given index x with y in the array.
  223. */
  224. public static <T> void swap(T[] array, int x, int y) {
  225. T tmpIndex = array[x];
  226. array[x] = array[y];
  227. array[y] = tmpIndex;
  228. }
  229. /**
  230. * Converts the given list of object type to its primitive counterpart.
  231. */
  232. public static int[] toPrimitiveArray(List<Integer> list) {
  233. int[] arr = new int[list.size()];
  234. int index = 0;
  235. for (Integer i : list) {
  236. Preconditions.checkNotNull(i);
  237. arr[index++] = i.intValue();
  238. }
  239. return arr;
  240. }
  241. /**
  242. * Converts the given array of object type to its primitive counterpart.
  243. */
  244. public static int[] toPrimitiveArray(Integer[] array) {
  245. int[] arr = new int[array.length];
  246. for (int i = 0; i < array.length; i++) {
  247. Preconditions.checkNotNull(array[i]);
  248. arr[i] = array[i];
  249. }
  250. return arr;
  251. }
  252. /**
  253. * Converts the given array of object type to its primitive counterpart.
  254. */
  255. public static long[] toPrimitiveArray(Long[] array) {
  256. long[] arr = new long[array.length];
  257. for (int i = 0; i < array.length; i++) {
  258. Preconditions.checkNotNull(array[i]);
  259. arr[i] = array[i];
  260. }
  261. return arr;
  262. }
  263. /**
  264. * Converts the given array of object type to its primitive counterpart.
  265. */
  266. public static double[] toPrimitiveArray(Double[] array) {
  267. double[] arr = new double[array.length];
  268. for (int i = 0; i < array.length; i++) {
  269. Preconditions.checkNotNull(array[i]);
  270. arr[i] = array[i];
  271. }
  272. return arr;
  273. }
  274. /**
  275. * Converts the given int array to a list of object wrappers.
  276. */
  277. public static List<Integer> toObjectList(int[] array) {
  278. ArrayList<Integer> lst = new ArrayList<>(array.length);
  279. for (int x : array)
  280. lst.add(x);
  281. return lst;
  282. }
  283. /**
  284. * Converts the given long array to a list of object wrappers.
  285. */
  286. public static List<Long> toObjectList(long[] array) {
  287. ArrayList<Long> lst = new ArrayList<>(array.length);
  288. for (long x : array)
  289. lst.add(x);
  290. return lst;
  291. }
  292. /**
  293. * Converts the given double array to a list of object wrappers.
  294. */
  295. public static List<Double> toObjectList(double[] array) {
  296. ArrayList<Double> lst = new ArrayList<>(array.length);
  297. for (double x : array)
  298. lst.add(x);
  299. return lst;
  300. }
  301. /**
  302. * Partitions the given array in-place and uses the last element as pivot,
  303. * everything less than the pivot will be placed left and everything greater
  304. * will be placed right of the pivot. It returns the index of the pivot
  305. * element after partitioning.
  306. */
  307. public static <T extends Comparable<T>> int partition(T[] array) {
  308. return partition(array, 0, array.length);
  309. }
  310. /**
  311. * Partitions the given array in-place and uses the end element as pivot,
  312. * everything less than the pivot will be placed left and everything greater
  313. * will be placed right of the pivot. It returns the index of the pivot
  314. * element after partitioning.
  315. */
  316. public static <T extends Comparable<T>> int partition(T[] array, int start,
  317. int end) {
  318. final int ending = end - 1;
  319. final T x = array[ending];
  320. int i = start - 1;
  321. for (int j = start; j < ending; j++) {
  322. if (array[j].compareTo(x) < 0) {
  323. i++;
  324. swap(array, i, j);
  325. }
  326. }
  327. i++;
  328. swap(array, i, ending);
  329. return i;
  330. }
  331. /**
  332. * Partitions the given array in-place and uses the last element as pivot,
  333. * everything less than the pivot will be placed left and everything greater
  334. * will be placed right of the pivot. It returns the index of the pivot
  335. * element after partitioning.
  336. */
  337. public static int partition(int[] array) {
  338. return partition(array, 0, array.length);
  339. }
  340. /**
  341. * Partitions the given array in-place and uses the end element as pivot,
  342. * everything less than the pivot will be placed left and everything greater
  343. * will be placed right of the pivot. It returns the index of the pivot
  344. * element after partitioning.
  345. */
  346. public static int partition(int[] array, int start, int end) {
  347. final int ending = end - 1;
  348. final int x = array[ending];
  349. int i = start - 1;
  350. for (int j = start; j < ending; j++) {
  351. if (array[j] <= x) {
  352. i++;
  353. swap(array, i, j);
  354. }
  355. }
  356. i++;
  357. swap(array, i, ending);
  358. return i;
  359. }
  360. /**
  361. * Partitions the given array in-place and uses the last element as pivot,
  362. * everything less than the pivot will be placed left and everything greater
  363. * will be placed right of the pivot. It returns the index of the pivot
  364. * element after partitioning.
  365. */
  366. public static int partition(long[] array) {
  367. return partition(array, 0, array.length);
  368. }
  369. /**
  370. * Partitions the given array in-place and uses the end element as pivot,
  371. * everything less than the pivot will be placed left and everything greater
  372. * will be placed right of the pivot. It returns the index of the pivot
  373. * element after partitioning.
  374. */
  375. public static int partition(long[] array, int start, int end) {
  376. final int ending = end - 1;
  377. final long x = array[ending];
  378. int i = start - 1;
  379. for (int j = start; j < ending; j++) {
  380. if (array[j] <= x) {
  381. i++;
  382. swap(array, i, j);
  383. }
  384. }
  385. i++;
  386. swap(array, i, ending);
  387. return i;
  388. }
  389. /**
  390. * Partitions the given array in-place and uses the last element as pivot,
  391. * everything less than the pivot will be placed left and everything greater
  392. * will be placed right of the pivot. It returns the index of the pivot
  393. * element after partitioning.
  394. */
  395. public static int partition(double[] array) {
  396. return partition(array, 0, array.length);
  397. }
  398. /**
  399. * Partitions the given array in-place and uses the end element as pivot,
  400. * everything less than the pivot will be placed left and everything greater
  401. * will be placed right of the pivot. It returns the index of the pivot
  402. * element after partitioning.
  403. */
  404. public static int partition(double[] array, int start, int end) {
  405. final int ending = end - 1;
  406. final double x = array[ending];
  407. int i = start - 1;
  408. for (int j = start; j < ending; j++) {
  409. if (array[j] <= x) {
  410. i++;
  411. swap(array, i, j);
  412. }
  413. }
  414. i++;
  415. swap(array, i, ending);
  416. return i;
  417. }
  418. /**
  419. * Selects the kth smallest element in the array in linear time, if the array
  420. * is smaller than or equal to 10 a radix sort will be used and the kth
  421. * element will be returned. So k = 1, will return the absolutely smallest
  422. * element.
  423. *
  424. * @return the kth smallest index of the element.
  425. */
  426. public static int quickSelect(int[] array, int k) {
  427. Preconditions.checkArgument(k > 0 && k <= array.length);
  428. final int n = array.length;
  429. if (n <= 10) {
  430. radixSort(array);
  431. return k - 1;
  432. }
  433. return quickSelect(array, 0, n, k);
  434. }
  435. /**
  436. * Selects the kth smallest element in the array.
  437. *
  438. * @param start the index where to start.
  439. * @param end the index where to end.
  440. * @return the kth smallest index of the element.
  441. */
  442. public static int quickSelect(int[] array, int start, int end, int k) {
  443. if (start == end) {
  444. return start;
  445. }
  446. final int pivot = partition(array, start, end);
  447. final int length = pivot - start + 1;
  448. if (length == k) {
  449. return pivot;
  450. } else if (k < length) {
  451. return quickSelect(array, start, pivot - 1, k);
  452. } else {
  453. return quickSelect(array, pivot + 1, end, k - length);
  454. }
  455. }
  456. /**
  457. * Selects the kth smallest element in the array in linear time. k = 1, will
  458. * return the absolutely smallest element.
  459. *
  460. * @return the kth smallest index of the element.
  461. */
  462. public static int quickSelect(double[] array, int k) {
  463. Preconditions.checkArgument(k > 0 && k <= array.length);
  464. return quickSelect(array, 0, array.length, k);
  465. }
  466. /**
  467. * Selects the kth smallest element in the array.
  468. *
  469. * @param start the index where to start.
  470. * @param end the index where to end.
  471. * @return the kth smallest index of the element.
  472. */
  473. public static int quickSelect(double[] array, int start, int end, int k) {
  474. if (start == end) {
  475. return start;
  476. }
  477. final int pivot = partition(array, start, end);
  478. final int length = pivot - start + 1;
  479. if (length == k) {
  480. return pivot;
  481. } else if (k < length) {
  482. return quickSelect(array, start, pivot - 1, k);
  483. } else {
  484. return quickSelect(array, pivot + 1, end, k - length);
  485. }
  486. }
  487. /**
  488. * Selects the kth smallest element in the array in linear time. k = 1, will
  489. * return the absolutely smallest element.
  490. *
  491. * @return the kth smallest index of the element.
  492. */
  493. public static int quickSelect(long[] array, int k) {
  494. Preconditions.checkArgument(k > 0 && k <= array.length);
  495. return quickSelect(array, 0, array.length, k);
  496. }
  497. /**
  498. * Selects the kth smallest element in the array.
  499. *
  500. * @param start the index where to start.
  501. * @param end the index where to end.
  502. * @return the kth smallest index of the element.
  503. */
  504. public static int quickSelect(long[] array, int start, int end, int k) {
  505. if (start == end) {
  506. return start;
  507. }
  508. final int pivot = partition(array, start, end);
  509. final int length = pivot - start + 1;
  510. if (length == k) {
  511. return pivot;
  512. } else if (k < length) {
  513. return quickSelect(array, start, pivot - 1, k);
  514. } else {
  515. return quickSelect(array, pivot + 1, end, k - length);
  516. }
  517. }
  518. /**
  519. * Selects the kth smallest element in the array in linear time. k = 1, will
  520. * return the absolutely smallest element.
  521. *
  522. * @return the kth smallest index of the element.
  523. */
  524. public static <T extends Comparable<T>> int quickSelect(T[] array, int k) {
  525. Preconditions.checkArgument(k > 0 && k <= array.length);
  526. return quickSelect(array, 0, array.length, k);
  527. }
  528. /**
  529. * Selects the kth smallest element in the array.
  530. *
  531. * @param start the index where to start.
  532. * @param end the index where to end.
  533. * @return the kth smallest index of the element.
  534. */
  535. public static <T extends Comparable<T>> int quickSelect(T[] array, int start,
  536. int end, int k) {
  537. if (start == end) {
  538. return start;
  539. }
  540. final int pivot = partition(array, start, end);
  541. final int length = pivot - start + 1;
  542. if (length == k) {
  543. return pivot;
  544. } else if (k < length) {
  545. return quickSelect(array, start, pivot - 1, k);
  546. } else {
  547. return quickSelect(array, pivot + 1, end, k - length);
  548. }
  549. }
  550. /**
  551. * Finds the median of medians in the given array.
  552. *
  553. * @return the index of the median of medians.
  554. */
  555. public static int medianOfMedians(int[] array) {
  556. final int splitSize = array.length / 5;
  557. if (splitSize <= 2) {
  558. radixSort(array);
  559. return array[array.length / 2];
  560. }
  561. int[] pivots = new int[splitSize];
  562. for (int i = 0; i < splitSize; i++) {
  563. final int start = i * 5;
  564. final int end = i * 5 + 5;
  565. pivots[i] = partition(array, start, end);
  566. }
  567. return pivots[splitSize / 2];
  568. }
  569. /**
  570. * Creates an integer array from the given start up to a end number with a
  571. * stepsize.
  572. *
  573. * @param from the integer to start with.
  574. * @param to the integer to end with.
  575. * @param stepsize the stepsize to take
  576. * @return an integer array from start to end incremented by stepsize.
  577. */
  578. public static int[] fromUpTo(int from, int to, int stepsize) {
  579. int[] v = new int[(to - from) / stepsize];
  580. for (int i = 0; i < v.length; i++) {
  581. v[i] = from + i * stepsize;
  582. }
  583. return v;
  584. }
  585. /**
  586. * Creates a long array from the given start up to a end number with a
  587. * stepsize.
  588. *
  589. * @param from the long to start with.
  590. * @param to the long to end with.
  591. * @param stepsize the stepsize to take
  592. * @return a long array from start to end incremented by stepsize.
  593. */
  594. public static long[] fromUpTo(long from, long to, long stepsize) {
  595. long[] v = new long[(int) ((to - from) / stepsize)];
  596. for (int i = 0; i < v.length; i++) {
  597. v[i] = from + i * stepsize;
  598. }
  599. return v;
  600. }
  601. /**
  602. * Creates a double array from the given start up to a end number with a
  603. * stepsize.
  604. *
  605. * @param from the double to start with.
  606. * @param to the double to end with.
  607. * @param stepsize the stepsize to take
  608. * @return a double array from start to end incremented by stepsize.
  609. */
  610. public static double[] fromUpTo(double from, double to, double stepsize) {
  611. double[] v = new double[(int) (Math.round(((to - from) / stepsize) + 0.5))];
  612. for (int i = 0; i < v.length; i++) {
  613. v[i] = from + i * stepsize;
  614. }
  615. return v;
  616. }
  617. /**
  618. * Radix sorts an integer array in O(m*n), where m is the length of the key
  619. * (here 32 bit) and n the number of elements. It only works for positive
  620. * numbers, so please don't come up with negative numbers, it will result in
  621. * array out of bound exceptions, since they don't have an array index.
  622. */
  623. public static void radixSort(int[] a) {
  624. int[] nPart = new int[2];
  625. int[][] part = new int[2][a.length];
  626. for (int i = 0; i < 32; i++) {
  627. nPart[0] = 0;
  628. nPart[1] = 0;
  629. for (int anA : a) {
  630. int n = (anA >> i) & 1;
  631. part[n][nPart[n]++] = anA;
  632. }
  633. System.arraycopy(part[0], 0, a, 0, nPart[0]);
  634. System.arraycopy(part[1], 0, a, nPart[0], nPart[1]);
  635. }
  636. }
  637. /**
  638. * Counting sort that sorts the integer array in O(n+k) where n is the number
  639. * of elements and k is the length of the integer intervals given (high -
  640. * low). So you can imagine that it uses domain knowledge of the contained
  641. * integers, like the lowest value and the highest. It only works for positive
  642. * numbers, so please don't come up with negative numbers, it will result in
  643. * array out of bound exceptions, since they don't have an array index.
  644. */
  645. public static void countingSort(int[] a, int low, int high) {
  646. final int[] counts = new int[high - low + 1];
  647. for (int x : a) {
  648. counts[x - low]++;
  649. }
  650. int current = 0;
  651. for (int i = 0; i < counts.length; i++) {
  652. Arrays.fill(a, current, current + counts[i], i + low);
  653. current += counts[i];
  654. }
  655. }
  656. /**
  657. * Quicksorts this array.
  658. */
  659. public static void quickSort(int[] a) {
  660. quickSort(a, 0, a.length);
  661. }
  662. /**
  663. * Quicksorts this array. With offset and length, this will be recursively
  664. * called by itself.
  665. */
  666. public static void quickSort(int[] a, int offset, int length) {
  667. if (offset < length) {
  668. int pivot = partition(a, offset, length);
  669. quickSort(a, offset, pivot);
  670. quickSort(a, pivot + 1, length);
  671. }
  672. }
  673. /**
  674. * Quicksorts this array.
  675. */
  676. public static void quickSort(long[] a) {
  677. quickSort(a, 0, a.length);
  678. }
  679. /**
  680. * Quicksorts this array. With offset and length, this will be recursively
  681. * called by itself.
  682. */
  683. public static void quickSort(long[] a, int offset, int length) {
  684. if (offset < length) {
  685. int pivot = partition(a, offset, length);
  686. quickSort(a, offset, pivot);
  687. quickSort(a, pivot + 1, length);
  688. }
  689. }
  690. /**
  691. * Quicksorts this array.
  692. */
  693. public static void quickSort(double[] a) {
  694. quickSort(a, 0, a.length);
  695. }
  696. /**
  697. * Quicksorts this array. With offset and length, this will be recursively
  698. * called by itself.
  699. */
  700. public static void quickSort(double[] a, int offset, int length) {
  701. if (offset < length) {
  702. int pivot = partition(a, offset, length);
  703. quickSort(a, offset, pivot);
  704. quickSort(a, pivot + 1, length);
  705. }
  706. }
  707. /**
  708. * Quicksorts this array.
  709. */
  710. public static <T extends Comparable<T>> void quickSort(T[] a) {
  711. quickSort(a, 0, a.length);
  712. }
  713. /**
  714. * Quicksorts this array. With offset and length, this will be recursively
  715. * called by itself.
  716. */
  717. public static <T extends Comparable<T>> void quickSort(T[] a, int offset,
  718. int length) {
  719. if (offset < length) {
  720. int pivot = partition(a, offset, length);
  721. quickSort(a, offset, pivot);
  722. quickSort(a, pivot + 1, length);
  723. }
  724. }
  725. /**
  726. * Multi-sorts the given arrays with the quicksort algorithm. It assumes that
  727. * all arrays have the same sizes and it sorts on the first dimension of these
  728. * arrays. If the given arrays are null or empty, it will do nothing, if just
  729. * a single array was passed it will sort it via {@link Arrays} sort;
  730. */
  731. public static void multiQuickSort(int[]... arrays) {
  732. multiQuickSort(0, arrays);
  733. }
  734. /**
  735. * Multi-sorts the given arrays with the quicksort algorithm. It assumes that
  736. * all arrays have the same sizes and it sorts on the given dimension index
  737. * (starts with 0) of these arrays. If the given arrays are null or empty, it
  738. * will do nothing, if just a single array was passed it will sort it via
  739. * {@link Arrays} sort;
  740. */
  741. public static void multiQuickSort(int sortDimension, int[]... arrays) {
  742. // check if the lengths are equal, break if everything is empty
  743. if (arrays == null || arrays.length == 0) {
  744. return;
  745. }
  746. // if the array only has a single dimension, sort it and return
  747. if (arrays.length == 1) {
  748. Arrays.sort(arrays[0]);
  749. return;
  750. }
  751. // also return if the sort dimension is not in our array range
  752. if (sortDimension < 0 || sortDimension >= arrays.length) {
  753. return;
  754. }
  755. // check sizes
  756. int firstArrayLength = arrays[0].length;
  757. for (int i = 1; i < arrays.length; i++) {
  758. if (arrays[i] == null || firstArrayLength != arrays[i].length)
  759. return;
  760. }
  761. multiQuickSort(arrays, 0, firstArrayLength, sortDimension);
  762. }
  763. /**
  764. * Internal multi quicksort, doing the real algorithm.
  765. */
  766. private static void multiQuickSort(int[][] a, int offset, int length,
  767. int indexToSort) {
  768. if (offset < length) {
  769. int pivot = multiPartition(a, offset, length, indexToSort);
  770. multiQuickSort(a, offset, pivot, indexToSort);
  771. multiQuickSort(a, pivot + 1, length, indexToSort);
  772. }
  773. }
  774. /**
  775. * Partitions the given array in-place and uses the end element as pivot,
  776. * everything less than the pivot will be placed left and everything greater
  777. * will be placed right of the pivot. It returns the index of the pivot
  778. * element after partitioning. This is a multi way partitioning algorithm, you
  779. * have to provide a partition array index to know which is the array that
  780. * needs to be partitioned. The swap operations are applied on the other
  781. * elements as well.
  782. */
  783. private static int multiPartition(int[][] array, int start, int end,
  784. int partitionArrayIndex) {
  785. final int ending = end - 1;
  786. final int x = array[partitionArrayIndex][ending];
  787. int i = start - 1;
  788. for (int j = start; j < ending; j++) {
  789. if (array[partitionArrayIndex][j] <= x) {
  790. i++;
  791. for (int[] anArray : array) {
  792. swap(anArray, i, j);
  793. }
  794. }
  795. }
  796. i++;
  797. for (int[] anArray : array) {
  798. swap(anArray, i, ending);
  799. }
  800. return i;
  801. }
  802. /**
  803. * Multi-sorts the given arrays with the quicksort algorithm. It assumes that
  804. * all arrays have the same sizes and it sorts on the first dimension of these
  805. * arrays. If the given arrays are null or empty, it will do nothing, if just
  806. * a single array was passed it will sort it via {@link Arrays} sort;
  807. */
  808. @SafeVarargs
  809. public static <T extends Comparable<T>> void multiQuickSort(T[]... arrays) {
  810. multiQuickSort(0, arrays);
  811. }
  812. /**
  813. * Multi-sorts the given arrays with the quicksort algorithm. It assumes that
  814. * all arrays have the same sizes and it sorts on the given dimension index
  815. * (starts with 0) of these arrays. If the given arrays are null or empty, it
  816. * will do nothing, if just a single array was passed it will sort it via
  817. * {@link Arrays} sort;
  818. */
  819. @SafeVarargs
  820. public static <T extends Comparable<T>> void multiQuickSort(
  821. int sortDimension, T[]... arrays) {
  822. // check if the lengths are equal, break if everything is empty
  823. if (arrays == null || arrays.length == 0) {
  824. return;
  825. }
  826. // if the array only has a single dimension, sort it and return
  827. if (arrays.length == 1) {
  828. Arrays.sort(arrays[0]);
  829. return;
  830. }
  831. // also return if the sort dimension is not in our array range
  832. if (sortDimension < 0 || sortDimension >= arrays.length) {
  833. return;
  834. }
  835. // check sizes
  836. int firstArrayLength = arrays[0].length;
  837. for (int i = 1; i < arrays.length; i++) {
  838. if (arrays[i] == null || firstArrayLength != arrays[i].length)
  839. return;
  840. }
  841. multiQuickSort(arrays, 0, firstArrayLength, sortDimension);
  842. }
  843. /**
  844. * Internal multi quicksort, doing the real algorithm.
  845. */
  846. private static <T extends Comparable<T>> void multiQuickSort(T[][] a,
  847. int offset, int length, int indexToSort) {
  848. if (offset < length) {
  849. int pivot = multiPartition(a, offset, length, indexToSort);
  850. multiQuickSort(a, offset, pivot, indexToSort);
  851. multiQuickSort(a, pivot + 1, length, indexToSort);
  852. }
  853. }
  854. /**
  855. * Partitions the given array in-place and uses the end element as pivot,
  856. * everything less than the pivot will be placed left and everything greater
  857. * will be placed right of the pivot. It returns the index of the pivot
  858. * element after partitioning. This is a multi way partitioning algorithm, you
  859. * have to provide a partition array index to know which is the array that
  860. * needs to be partitioned. The swap operations are applied on the other
  861. * elements as well.
  862. */
  863. private static <T extends Comparable<T>> int multiPartition(T[][] array,
  864. int start, int end, int partitionArrayIndex) {
  865. final int ending = end - 1;
  866. final T x = array[partitionArrayIndex][ending];
  867. int i = start - 1;
  868. for (int j = start; j < ending; j++) {
  869. if (array[partitionArrayIndex][j].compareTo(x) < 0) {
  870. i++;
  871. for (T[] anArray : array) {
  872. swap(anArray, i, j);
  873. }
  874. }
  875. }
  876. i++;
  877. for (T[] anArray : array) {
  878. swap(anArray, i, ending);
  879. }
  880. return i;
  881. }
  882. /**
  883. * Deduplicates an array in linear time, it does not change the order of the
  884. * elements.
  885. */
  886. public static int[] deduplicate(int[] arr) {
  887. if (arr.length <= 1)
  888. return arr;
  889. TIntArrayList list = new TIntArrayList();
  890. TIntHashSet set = new TIntHashSet();
  891. for (int a : arr) {
  892. if (set.add(a)) {
  893. list.add(a);
  894. }
  895. }
  896. return list.toArray();
  897. }
  898. /**
  899. * Deduplicates an array in linear time, it does not change the order of the
  900. * elements. Note that equals and hashcode must be overridden for this to
  901. * work.
  902. */
  903. public static <T> ArrayList<T> deduplicate(T[] arr) {
  904. ArrayList<T> list = new ArrayList<>();
  905. HashSet<T> set = new HashSet<>();
  906. for (T a : arr) {
  907. if (set.add(a)) {
  908. list.add(a);
  909. }
  910. }
  911. return list;
  912. }
  913. /**
  914. * Computes the union of two arrays.
  915. */
  916. public static int[] union(int[] a, int[] b) {
  917. TIntHashSet set = new TIntHashSet();
  918. set.addAll(a);
  919. set.addAll(b);
  920. return set.toArray();
  921. }
  922. /**
  923. * Computes the intersection of two <b>sorted</b> arrays. Will deduplicate the
  924. * items, so the return is a set of integers.
  925. */
  926. public static int[] intersection(int[] arr, int[] arr2) {
  927. TIntArrayList lst = new TIntArrayList();
  928. int i = 0, j = 0;
  929. while (i < arr.length && j < arr2.length) {
  930. if (arr[i] == arr2[j]) {
  931. // only add if the last element we've added wasn't included yet
  932. if (lst.isEmpty() || lst.get(lst.size() - 1) < arr[i])
  933. lst.add(arr[i]);
  934. i++;
  935. j++;
  936. } else if (arr[i] > arr2[j]) {
  937. j++;
  938. } else {
  939. i++;
  940. }
  941. }
  942. return lst.toArray();
  943. }
  944. /**
  945. * Computes the intersection of two <b>unsorted</b> arrays. Will deduplicate
  946. * the items, so the return is a set of integers.
  947. */
  948. public static int[] intersectionUnsorted(int[] arr, int[] arr2) {
  949. TIntHashSet set = new TIntHashSet();
  950. TIntHashSet toReturn = new TIntHashSet();
  951. for (int a : arr) {
  952. set.add(a);
  953. }
  954. for (int a : arr2) {
  955. if (set.contains(a)) {
  956. toReturn.add(a);
  957. }
  958. }
  959. return toReturn.toArray();
  960. }
  961. /**
  962. * If array contains unique integers in a range between 0 and n-1, this
  963. * function finds the only one missing in linear time and constant memory.
  964. * This is more of a typical homework or interview question than of actually
  965. * use. <br/>
  966. * The trick is to sum the items in the array and then calculate the expected
  967. * sum of the elements, then diff and return the value.
  968. */
  969. public static int missingNumber(int[] array) {
  970. int sum = 0;
  971. for (int x : array) {
  972. sum += x;
  973. }
  974. return ((array.length) * (array.length + 1) / 2) - sum;
  975. }
  976. /**
  977. * @return the min value in this array,
  978. */
  979. public static int min(int[] array) {
  980. Preconditions.checkNotNull(array, "array must not be null");
  981. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  982. int minValue = array[0];
  983. for (int aVector : array) {
  984. if (minValue > aVector) {
  985. minValue = aVector;
  986. }
  987. }
  988. return minValue;
  989. }
  990. /**
  991. * @return the minimum index in this array,
  992. */
  993. public static int minIndex(int[] array) {
  994. Preconditions.checkNotNull(array, "array must not be null");
  995. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  996. int minIndex = 0;
  997. for (int i = 0; i < array.length; i++) {
  998. if (array[minIndex] > array[i]) {
  999. minIndex = i;
  1000. }
  1001. }
  1002. return minIndex;
  1003. }
  1004. /**
  1005. * @return the minimum value in this array,
  1006. */
  1007. public static long min(long[] array) {
  1008. Preconditions.checkNotNull(array, "array must not be null");
  1009. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1010. long minValue = array[0];
  1011. for (long aVector : array) {
  1012. if (minValue > aVector) {
  1013. minValue = aVector;
  1014. }
  1015. }
  1016. return minValue;
  1017. }
  1018. /**
  1019. * @return the minimum index in this array,
  1020. */
  1021. public static int minIndex(long[] array) {
  1022. Preconditions.checkNotNull(array, "array must not be null");
  1023. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1024. int minIndex = 0;
  1025. for (int i = 0; i < array.length; i++) {
  1026. if (array[minIndex] > array[i]) {
  1027. minIndex = i;
  1028. }
  1029. }
  1030. return minIndex;
  1031. }
  1032. /**
  1033. * @return the minimum value in this array,
  1034. */
  1035. public static double min(double[] array) {
  1036. Preconditions.checkNotNull(array, "array must not be null");
  1037. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1038. double minValue = array[0];
  1039. for (double aVector : array) {
  1040. if (minValue > aVector) {
  1041. minValue = aVector;
  1042. }
  1043. }
  1044. return minValue;
  1045. }
  1046. /**
  1047. * @return the minimum index in this array,
  1048. */
  1049. public static int minIndex(double[] array) {
  1050. Preconditions.checkNotNull(array, "array must not be null");
  1051. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1052. int minIndex = 0;
  1053. for (int i = 0; i < array.length; i++) {
  1054. if (array[minIndex] > array[i]) {
  1055. minIndex = i;
  1056. }
  1057. }
  1058. return minIndex;
  1059. }
  1060. /**
  1061. * @return the maximum value in this array,
  1062. */
  1063. public static int max(int[] array) {
  1064. Preconditions.checkNotNull(array, "array must not be null");
  1065. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1066. int maxValue = array[0];
  1067. for (int aVector : array) {
  1068. if (maxValue < aVector) {
  1069. maxValue = aVector;
  1070. }
  1071. }
  1072. return maxValue;
  1073. }
  1074. /**
  1075. * @return the maximum index in this array,
  1076. */
  1077. public static int maxIndex(int[] array) {
  1078. Preconditions.checkNotNull(array, "array must not be null");
  1079. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1080. int maxIndex = 0;
  1081. for (int i = 0; i < array.length; i++) {
  1082. if (array[maxIndex] < array[i]) {
  1083. maxIndex = i;
  1084. }
  1085. }
  1086. return maxIndex;
  1087. }
  1088. /**
  1089. * @return the maximum value in this array,
  1090. */
  1091. public static long max(long[] array) {
  1092. Preconditions.checkNotNull(array, "array must not be null");
  1093. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1094. long maxValue = array[0];
  1095. for (long aVector : array) {
  1096. if (maxValue < aVector) {
  1097. maxValue = aVector;
  1098. }
  1099. }
  1100. return maxValue;
  1101. }
  1102. /**
  1103. * @return the maximum index in this array,
  1104. */
  1105. public static int maxIndex(long[] array) {
  1106. Preconditions.checkNotNull(array, "array must not be null");
  1107. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1108. int maxIndex = 0;
  1109. for (int i = 0; i < array.length; i++) {
  1110. if (array[maxIndex] < array[i]) {
  1111. maxIndex = i;
  1112. }
  1113. }
  1114. return maxIndex;
  1115. }
  1116. /**
  1117. * @return the maximum value in this array,
  1118. */
  1119. public static double max(double[] array) {
  1120. Preconditions.checkNotNull(array, "array must not be null");
  1121. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1122. double maxValue = array[0];
  1123. for (double aVector : array) {
  1124. if (maxValue < aVector) {
  1125. maxValue = aVector;
  1126. }
  1127. }
  1128. return maxValue;
  1129. }
  1130. /**
  1131. * @return the maximum index in this array,
  1132. */
  1133. public static int maxIndex(double[] array) {
  1134. Preconditions.checkNotNull(array, "array must not be null");
  1135. Preconditions.checkArgument(array.length > 0, "array must not be empty");
  1136. int maxIndex = 0;
  1137. for (int i = 0; i < array.length; i++) {
  1138. if (array[maxIndex] < array[i]) {
  1139. maxIndex = i;
  1140. }
  1141. }
  1142. return maxIndex;
  1143. }
  1144. /**
  1145. * Splits the given array from 0 to the given splitindex (included).
  1146. *
  1147. * @return a new array with the same objects in array[0..splitIndex]
  1148. */
  1149. public static <T> T[] subArray(T[] array, int splitIndex) {
  1150. return subArray(array, 0, splitIndex);
  1151. }
  1152. /**
  1153. * Splits the given array from the given startIndex to the given splitIndex
  1154. * (included).
  1155. *
  1156. * @return a new array with the same objects in array[startIndex..splitIndex]
  1157. */
  1158. public static <T> T[] subArray(T[] array, int startIndex, int splitIndex) {
  1159. @SuppressWarnings("unchecked")
  1160. T[] subArray = (T[]) Array.newInstance(array.getClass().getComponentType(),
  1161. splitIndex - startIndex + 1);
  1162. System.arraycopy(array, startIndex, subArray, 0, subArray.length);
  1163. return subArray;
  1164. }
  1165. /**
  1166. * Shuffles the given array.
  1167. *
  1168. * @return mutated parameter array that was shuffled beforehand.
  1169. */
  1170. public static <T> T[] shuffle(T[] array) {
  1171. return shuffle(array, new Random());
  1172. }
  1173. /**
  1174. * Shuffles the given array with the given random function.
  1175. *
  1176. * @return mutated parameter array that was shuffled beforehand.
  1177. */
  1178. public static <T> T[] shuffle(T[] array, Random rnd) {
  1179. for (int i = array.length; i > 1; i--)
  1180. swap(array, i - 1, rnd.nextInt(i));
  1181. return array;
  1182. }
  1183. /**
  1184. * Shuffles the given array.
  1185. *
  1186. * @return mutated parameter array that was shuffled beforehand.
  1187. */
  1188. @SafeVarargs
  1189. public static <T> T[] multiShuffle(T[] array, T[]... additions) {
  1190. return multiShuffle(array, new Random(), additions);
  1191. }
  1192. /**
  1193. * Shuffles the given array with the given random function.
  1194. *
  1195. * @return mutated parameter array that was shuffled beforehand.
  1196. */
  1197. @SafeVarargs
  1198. public static <T> T[] multiShuffle(T[] array, Random rnd, T[]... additions) {
  1199. for (int i = array.length; i > 1; i--) {
  1200. final int swapIndex = rnd.nextInt(i);
  1201. swap(array, i - 1, swapIndex);
  1202. for (T[] arr : additions) {
  1203. swap(arr, i - 1, swapIndex);
  1204. }
  1205. }
  1206. return array;
  1207. }
  1208. /**
  1209. * Creates the given array from a varargs parameter.
  1210. *
  1211. * @param arrays the array to create.
  1212. * @return the inputted stuff as array.
  1213. */
  1214. public static int[] create(int... arrays) {
  1215. return arrays;
  1216. }
  1217. /**
  1218. * Creates the given array from a varargs parameter.
  1219. *
  1220. * @param arrays the array to create.
  1221. * @return the inputted stuff as array.
  1222. */
  1223. public static long[] create(long... arrays) {
  1224. return arrays;
  1225. }
  1226. /**
  1227. * Creates the given array from a varargs parameter.
  1228. *
  1229. * @param arrays the array to create.
  1230. * @return the inputted stuff as array.
  1231. */
  1232. public static double[] create(double... arrays) {
  1233. return arrays;
  1234. }
  1235. /**
  1236. * Creates the given array from a varargs parameter.
  1237. *
  1238. * @param arrays the array to create.
  1239. * @return the inputted stuff as array.
  1240. */
  1241. public static byte[] create(byte... arrays) {
  1242. return arrays;
  1243. }
  1244. /**
  1245. * Creates the given array from a varargs parameter.
  1246. *
  1247. * @param arrays the array to create.
  1248. * @return the inputted stuff as array.
  1249. */
  1250. @SafeVarargs
  1251. public static <T> T[] create(T... arrays) {
  1252. return arrays;
  1253. }
  1254. /**
  1255. * Merges two sorted arrays to a single new array.
  1256. *
  1257. * @param a sorted array.
  1258. * @param b sorted array.
  1259. * @return a new array that merged both into a new sorted array.
  1260. */
  1261. public static int[] merge(int[] a, int[] b) {
  1262. int[] toReturn = new int[a.length + b.length];
  1263. int i = 0, j = 0, k = 0;
  1264. while (i < a.length && j < b.length) {
  1265. if (a[i] < b[j]) {
  1266. toReturn[k] = a[i];
  1267. i++;
  1268. } else {
  1269. toReturn[k] = b[j];
  1270. j++;
  1271. }
  1272. k++;
  1273. }
  1274. System.arraycopy(a, i, toReturn, k, a.length - i);
  1275. System.arraycopy(b, j, toReturn, k + a.length - i, b.length - j);
  1276. return toReturn;
  1277. }
  1278. /**
  1279. * Merges two sorted subparts of the given number array. E.G: if you want to
  1280. * merge { 1, 2, 5, 3, 5, 6, 7 } you have to pass merge(concat, 0, 2, 6),
  1281. * because you are starting at zero, the second sorted array begins at index
  1282. * 3, so it is 3-1=2. The end is the length of the array - 1.
  1283. *
  1284. * @param numbers the array which has two sorted sub arrays.
  1285. * @param startIndexA the start index of the first sorted array.
  1286. * @param endIndexA the end index of the first sorted array.
  1287. * @param endIndexB the end of the second array.
  1288. */
  1289. public static void merge(int[] numbers, int startIndexA, int endIndexA,
  1290. int endIndexB) {
  1291. int[] toReturn = new int[endIndexB - startIndexA + 1];
  1292. int i = 0, k = startIndexA, j = endIndexA + 1;
  1293. while (i < toReturn.length) {
  1294. if (numbers[k] < numbers[j]) {
  1295. toReturn[i] = numbers[k];
  1296. k++;
  1297. } else {
  1298. toReturn[i] = numbers[j];
  1299. j++;
  1300. }
  1301. i++;
  1302. // if we hit the limit of an array, copy the rest
  1303. if (j > endIndexB) {
  1304. System.arraycopy(numbers, k, toReturn, i, endIndexA - k + 1);
  1305. break;
  1306. }
  1307. if (k > endIndexA) {
  1308. System.arraycopy(numbers, j, toReturn, i, endIndexB - j + 1);
  1309. break;
  1310. }
  1311. }
  1312. System.arraycopy(toReturn, 0, numbers, startIndexA, toReturn.length);
  1313. }
  1314. /**
  1315. * @return true if the given index is inside the array range between 0 and
  1316. * array.length (exclusive).
  1317. */
  1318. public static boolean isValidIndex(int[] array, int index) {
  1319. return index >= 0 && index < array.length;
  1320. }
  1321. /**
  1322. * @return true if the given index is inside the array range between 0 and
  1323. * array.length (exclusive).
  1324. */
  1325. public static boolean isValidIndex(double[] array, int index) {
  1326. return index >= 0 && index < array.length;
  1327. }
  1328. /**
  1329. * @return true if the given index is inside the array range between 0 and
  1330. * array.length (exclusive).
  1331. */
  1332. public static boolean isValidIndex(float[] array, int index) {
  1333. return index >= 0 && index < array.length;
  1334. }
  1335. /**
  1336. * @return true if the given index is inside the array range between 0 and
  1337. * array.length (exclusive).
  1338. */
  1339. public static boolean isValidIndex(long[] array, int index) {
  1340. return index >= 0 && index < array.length;
  1341. }
  1342. /**
  1343. * @return true if the given index is inside the array range between 0 and
  1344. * array.length (exclusive).
  1345. */
  1346. public static boolean isValidIndex(boolean[] array, int index) {
  1347. return index >= 0 && index < array.length;
  1348. }
  1349. /**
  1350. * @return true if the given index is inside the array range between 0 and
  1351. * array.length (exclusive).
  1352. */
  1353. public static boolean isValidIndex(byte[] array, int index) {
  1354. return index >= 0 && index < array.length;
  1355. }
  1356. /**
  1357. * @return true if the given index is inside the array range between 0 and
  1358. * array.length (exclusive).
  1359. */
  1360. public static <T> boolean isValidIndex(T[] array, int index) {
  1361. return index >= 0 && index < array.length;
  1362. }
  1363. }