PageRenderTime 101ms CodeModel.GetById 9ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

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