Author: Jacob Park
package sorting.insertion_sort;
class InsertionSort {
public static void insertionSort(int[] S) {
// For every element,
for (int index = 0; index < S.length; index++) {
/*
* Sink the element leftwards to the head
* such that the array is sorted.
*/
for (int subIndex = index;
subIndex > 0 && S[subIndex] < S[subIndex - 1];
subIndex--) {
final int temporary = S[subIndex];
S[subIndex] = S[subIndex - 1];
S[subIndex - 1] = temporary;
}
}
}
}
package sorting.insertion_sort;
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
InsertionSort.insertionSort(S);
System.out.println(Arrays.toString(S));
package sorting.merge_sort;
class MergeSort {
public static void mergeSort(
int[] S,
int[] buffer,
int headIndex,
int tailIndex) {
if (headIndex >= tailIndex) {
return;
}
final int medianIndex = headIndex + (tailIndex - headIndex) / 2;
mergeSort(S, buffer, headIndex, medianIndex);
mergeSort(S, buffer, medianIndex + 1, tailIndex);
merge(S, buffer, headIndex, medianIndex, tailIndex);
}
private static void merge(
int[] S,
int[] buffer,
int headIndex,
int medianIndex,
int tailIndex) {
// Copy the left and the right slices into buffer.
for (int index = headIndex; index <= tailIndex; index++) {
buffer[index] = S[index];
}
int lowerIndex = headIndex;
int upperIndex = medianIndex + 1;
int index = headIndex;
/*
* Take the minimum of the left and the right slice
* until one is empty.
*/
while (lowerIndex <= medianIndex && upperIndex <= tailIndex) {
if (buffer[lowerIndex] <= buffer[upperIndex]) {
S[index++] = buffer[lowerIndex++];
} else {
S[index++] = buffer[upperIndex++];
}
}
// Flush the left slice.
while (lowerIndex <= medianIndex) {
S[index++] = buffer[lowerIndex++];
}
// Flush the right slice.
while (upperIndex <= tailIndex) {
S[index++] = buffer[upperIndex++];
}
}
}
package sorting.merge_sort;
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
final int[] buffer = new int[S.length];
MergeSort.mergeSort(S, buffer, 0, S.length - 1);
System.out.println(Arrays.toString(S));
package sorting.quick_sort;
class QuickSort {
public static void quickSort(int[] S, int headIndex, int tailIndex) {
if (headIndex >= tailIndex) {
return;
}
final int pivotIndex = partition(S, headIndex, tailIndex);
quickSort(S, headIndex, pivotIndex - 1);
quickSort(S, pivotIndex + 1, tailIndex);
}
/*
* Partition the array with the sentinel as the pivot.
* All elements before the sentinel should be less
* than the sentinel.
* All elements after the sentinel should be greater
* than the sentinel.
*/
private static int partition(int[] S, int headIndex, int tailIndex) {
// Choose the head as the sentinel.
final int sentinel = S[headIndex];
int lowerIndex = headIndex;
int upperIndex = tailIndex + 1;
while (true) {
/*
* Find the first element starting up from lower index
* that is greater than the sentinel.
*/
while (S[++lowerIndex] < sentinel && lowerIndex < tailIndex);
/*
* Find the first element starting down from upper index
* that is lesser than the sentinel.
*/
while (S[--upperIndex] > sentinel && upperIndex > headIndex);
if (lowerIndex >= upperIndex) {
break;
}
/*
* Swap an element lesser than the sentinel with
* an element greater than the sentinel.
*/
final int temporary = S[lowerIndex];
S[lowerIndex] = S[upperIndex];
S[upperIndex] = temporary;
}
// Swap sentinel to its pivot location.
S[headIndex] = S[upperIndex];
S[upperIndex] = sentinel;
return upperIndex;
}
}
package sorting.quick_sort;
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
QuickSort.quickSort(S, 0, S.length - 1);
System.out.println(Arrays.toString(S));
package sorting.counting_sort;
class CountingSort {
public static void countingSort(int[] S, int cardinality) {
final int[] counts = new int[cardinality];
final int[] buffer = new int[S.length];
// Count all distinct elements in S.
for (int index = 0; index < S.length; index++) {
counts[S[index]]++;
}
/*
* Inductively, augment counts to contain the sorted positions.
*
* Intuition: You can only be inserted into the sorted array,
* until after all values smaller than you have been inserted.
*/
for (int index = 1; index < cardinality; index++) {
counts[index] += counts[index - 1];
}
// Map S to its sorted positions into buffer.
for (int index = 0; index < S.length; index++) {
/*
* Decrement because counts start from 1,
* and array indices start from 0.
*/
buffer[--counts[S[index]]] = S[index];
}
// Flush the buffer into S.
for (int index = 0; index < S.length; index++) {
S[index] = buffer[index];
}
}
}
package sorting.counting_sort;
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
CountingSort.countingSort(S, 8);
System.out.println(Arrays.toString(S));
package sorting.radix_sort;
import java.util.Arrays;
import java.util.Collections;
class RadixSort {
/*
* Because counting sort is stable,
* we can sort S by digits of 10 from 1s to 10...0s.
*/
public static void radixSort(int[] S) {
int maximum = S[0];
for (int index = 0; index < S.length; index++) {
if (maximum < S[index]) {
maximum = S[index];
}
}
for (int exp = 1; (maximum / exp) > 0; exp *= 10) {
countingSort(S, exp);
}
}
private static void countingSort(int[] S, int exp) {
final int[] counts = new int[10];
final int[] buffer = new int[S.length];
for (int index = 0; index < S.length; index++) {
counts[(S[index] / exp) % 10]++;
}
for (int index = 1; index < 10; index++) {
counts[index] += counts[index - 1];
}
for (int index = 0; index < S.length; index++) {
buffer[--counts[(S[index] / exp) % 10]] = S[index];
}
for (int index = 0; index < S.length; index++) {
S[index] = buffer[index];
}
}
}
package sorting.radix_sort;
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
RadixSort.radixSort(S);
System.out.println(Arrays.toString(S));
If an array is sorted, binary search can test whether an element exists in $O(\log(n)$ time.
package sorting.binary_search;
class BinarySearch {
// Classic:
public static int binarySearch(int[] S, int key) {
int headIndex = 0;
int tailIndex = S.length - 1;
while (headIndex <= tailIndex) {
final int medianIndex = headIndex + (tailIndex - headIndex) / 2;
if (key < S[medianIndex]) {
tailIndex = medianIndex - 1;
} else if (key > S[medianIndex]) {
headIndex = medianIndex + 1;
} else {
return medianIndex;
}
}
return -1;
}
// Alternative:
// Advantage: Returns where key should be inserted.
public static int alternativeSearch(int[] S, int key) {
int index = 0;
for (int offset = S.length / 2; offset >= 1; offset /= 2) {
while ((index + offset) < S.length && S[index + offset] <= key) {
index += offset;
}
}
return index;
}
}
S[i - 1] == S[i]
to find duplicates.import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
Arrays.sort(S);
for (int i = 1; i < S.length; i++) {
if (S[i - 1] == S[i]) {
System.out.println("Not Unique");
}
}
S[back] != S[i]
.S[back] != S[i]
, increment back
and copy S[i]
to S[back]
.import java.util.Arrays;
int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
Arrays.sort(S);
int back = 0;
int length = S.length;
for (int i = 1; i < S.length; i++) {
if (S[back] != S[i]) {
back++;
S[back] = S[i];
} else {
length--;
}
}
S = Arrays.copyOf(S, length);
System.out.println(Arrays.toString(S));
package sorting.prioritizing_events;
class Event {
final int date;
final int item;
public Event(int date, int item) {
this.date = date;
this.item = item;
}
@Override
public String toString() {
return String.format(
"Event(date=%d,item=%d)",
this.date,
this.item
);
}
}
package sorting.prioritizing_events;
import java.lang.Integer;
import java.util.Comparator;
class EventDateComparator implements Comparator<Event> {
@Override
public int compare(Event o1, Event o2) {
return Integer.compare(o1.date, o2.date);
}
}
package sorting.prioritizing_events;
import java.util.Arrays;
Event[] S = new Event[] {
new Event(7, 5),
new Event(0, 1),
new Event(6, 2),
new Event(4, 2)
};
Arrays.sort(S, new EventDateComparator());
System.out.println(Arrays.toString(S));
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
Arrays.sort(S);
System.out.println(String.format("Minimum: %d", S[0]));
System.out.println(String.format("Maximum: %d", S[S.length - 1]));
System.out.println(String.format("Median: %d", S[S.length / 2]));
S[i - 1] == S[i]
to maintain a running count or frequency of the item until S[i - 1] != S[i]
.import java.util.Arrays;
final int[] S = new int[] {4, 4, 1, 2, 0, 1, 3, 6, 5, 1, 0, 7, 1, 4, 1, 4};
Arrays.sort(S);
int frequency = 1;
for (int i = 1; i < S.length; i++) {
if (S[i - 1] != S[i]) {
System.out.println(
String.format("Frequency of %d: %d", S[i - 1], frequency)
);
frequency = 1;
} else {
frequency++;
}
}
System.out.println(
String.format("Frequency of %d: %d", S[S.length - 1], frequency)
);
import java.util.Arrays;
final int[] A = new int[] {7, 4, 5, 0, 6, 3};
final int[] B = new int[] {5, 0, 4, 1, 7, 2};
int[] C = new int[A.length + B.length];
Arrays.sort(A);
Arrays.sort(B);
int i = 0;
int j = 0;
int k = 0;
while (i < A.length && j < B.length) {
if (A[i] < B[j]) {
C[k++] = A[i++];
} else if (A[i] > B[j]) {
C[k++] = B[j++];
} else {
C[k++] = A[i];
i++;
j++;
}
}
while (i < A.length) {
C[k++] = A[i++];
}
while (i < B.length) {
C[k++] = B[j++];
}
C = Arrays.copyOf(C, k);
System.out.println(String.format("Union: %s", Arrays.toString(C)));
import java.lang.Math;
import java.util.Arrays;
final int[] A = new int[] {7, 4, 5, 0, 6, 3};
final int[] B = new int[] {5, 0, 4, 1, 7, 2};
int[] C = new int[Math.min(A.length, B.length)];
Arrays.sort(A);
Arrays.sort(B);
int i = 0;
int j = 0;
int k = 0;
while (i < A.length && j < B.length) {
if (A[i] < B[j]) {
i++;
} else if (A[i] > B[j]) {
j++;
} else {
C[k++] = A[i];
i++;
j++;
}
}
C = Arrays.copyOf(C, k);
System.out.println(String.format("Intersection: %s", Arrays.toString(C)));
x + y == z
)¶S[i]
increases with i
, decrease j
such that (S[i] + S[j]) == z
.import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 3, 4, 2};
Arrays.sort(S);
int i = 0;
int j = S.length - 1;
while (i < S.length && j >= 0) {
if ((S[i] + S[j]) == 3) {
System.out.println(String.format("%d + %d = 3", S[i], S[j]));
break;
} else if ((S[i] + S[j]) > 3) {
j--;
} else {
i++;
}
}
import java.util.Arrays;
final int[] S = new int[] {7, 5, 0, 1, 6, 2, 4, 2};
Arrays.sort(S);
System.out.println(
String.format("Exists: %b", S[Arrays.binarySearch(S, 1)] == S[1])
);