Post on 19-Jan-2016
1
Contest AlgorithmsJanuary 2016
Pseudo-code for divide and conquer, and three examples (binary exponentiation, binary search, and mergesort).
5. Divide & Conquer
Contest Algorithms: 5. Divide & Conquer
1. Divide-and-Conquer
1. Divide problem into two or more smaller instances
2. Solve smaller instances recursively (conquer)
3. Obtain solution to original (larger) problem by combining these solutions
Divide-and-Conquer Technique
solvesubproblem 2
of size n/2
a solution to subproblem 1
a solution tothe original problem
solve a problem of size n
a recursive algorithm
combine solutions
solvesubproblem 1
of size n/2
divide problem into smaller parts (often 2)
a solution to subproblem 2
Divide-and-Conquer Examples
Binary exponentiation Binary search Sorting: mergesort and quicksort
(see QuickSort.java)
Closest Pair of Points Problem see the Computational Geometry slides
5
2. Binary Exponentiation : xn
public static long pow(long x, long n) { if (n <= 0) // n must be positive return 1; else if (n % 2 == 1) { // odd long p = pow(x, (n-1)/2); // pow of x faster than x2
return x * p * p; } else { // n even long p = pow(x, n/2); return p * p; } } // end of pow()
see Power.java
Contest Algorithms: 4. Backtracking
6
Java interprets all numeral literals as 32-bit integers. e.g. long x = 30000000;
// will give "integer number too large" error
int range: -2147483648 to 2147483647 (231-1)
If you want to write something bigger than a 32-bit integer, use the suffix L:
e.g. long x = 30000000L; // accepted
Writing long numbers
Contest Algorithms: 4. Backtracking
7
public static void main (String[] args){ System.out.println("5^2 = " + pow(5,2)); System.out.println("2^10 = " + pow(2,10));
for (int i=10; i <= 100; i=i+5) System.out.println("2^" + i + " = " + pow(2,i));} // end of main()
Using pow()
Contest Algorithms: 4. Backtracking
8
Problems with overflow: Three ways to solve it
write youe own multiply() use Math.multiplyExact()
in Java 8 use BigInteger
see "Maths" slides BigInteger.pow(int
exponent)
Contest Algorithms: 4. Backtracking
9
public static long mult(long a, long b) { if ((a != 0) && (b > Long.MAX_VALUE / a)) // detect overflow System.out.println("Overflow for a*b:\n " + a + " * " + b); return a*b; }
In pow(), replace the three uses of "*": return mult(x, mult(p, p)); // was x * p * p return mult(p, p); // was p * p
Your own multiply()
Contest Algorithms: 4. Backtracking
10
Contest Algorithms: 4. Backtracking
11
In pow(), replace the three uses of "*":
return Math.multiplyExact(x, Math.multiplyExact(p,p)); // was x * p * p
return Math.multiplyExact(p, p); // was p * p
Use Math.multiplyExact()
Contest Algorithms: 4. Backtracking
12
Contest Algorithms: 4. Backtracking
13
addExact(), subtractExact(), multiplyExact() incrementExact(), decrementExact() toIntExact()
used when casting a long to an int
Instead of silently giving the wrong answer, they will throw a java.lang.ArithmeticException for overflows involving int or long calculations
Java 8 "Exact" Math methods
Binary Search is a divide and conquer algorithm.
Find an element in a sorted array:1. Divide: Check middle element.2. Conquer: Recursively search 1 subarray.3. Combine: Easy; return index
3. Binary Search
Example: Find 9
3 5 7 8 9 12 15
As implemented in Java byArrays.binarySearch()
Example
Example: Find 9
3 5 7 8 9 12 15
Find an element in a sorted array:
1.Divide: Check middle element.2.Conquer: Recursively search 1
subarray.3.Combine: Trivial.
Example: Find 9
3 5 7 8 9 12 15
Find an element in a sorted array:
1.Divide: Check middle element.2.Conquer: Recursively search 1
subarray.3.Combine: Trivial.
Example: Find 9
3 5 7 8 9 12 15
Find an element in a sorted array:
1.Divide: Check middle element.2.Conquer: Recursively search 1
subarray.3.Combine: Trivial.
Example: Find 9
3 5 7 8 9 12 15
Find an element in a sorted array:
1.Divide: Check middle element.2.Conquer: Recursively search 1
subarray.3.Combine: Trivial.
Find an element in a sorted array:
1.Divide: Check middle element.2.Conquer: Recursively search 1
subarray.3.Combine: Trivial.
Example: Find 9
3 5 7 8 9 12 15
Binary Search Code private static int binarySearch(int[] arr, int val) { return binSrch(arr, val, 0, arr.length-1); }
private static int binSrch(int[] arr, int val, int start, int end) { if (start > end) // val not found return -1;
int middle = (start + end)/2; int midVal = arr[middle]; if (val == midVal) return middle; else if (val > midVal) // search right half return binSrch(arr, val, middle+1, end); else // search left half return binSrch(arr, val, start, middle-1); } // end of binSrch()
see BinarySearchTest.java
Contest Algorithms: 4. Backtracking
21
public static void main (String[] args){ Integer[] intArr = {2, 3, 5, 7, 9, 10, 13, 15, 17, 19}; System.out.println("Index pos of 10: " +
Arrays.binarySearch(intArr, 10)); System.out.println("Index pos of 22: " +
Arrays.binarySearch(intArr, 22)); int[] arr = {2, 3, 5, 7, 9, 10, 13, 15, 17, 19}; System.out.println("Index pos of 10: " + binarySearch(arr, 10)); System.out.println("Index pos of 22: " + binarySearch(arr, 22));} // end of main()
Using Both Functions
Index pos of 10: 5Index pos of 22: -11Index pos of 10: 5Index pos of 22: -1
22
4. Mergesort
A stable sorting algorithm with worst-case running time O(n log n)
Algorithm: Divide the list into two sub-lists Sort each sub-list (recursion) Merge the two sorted sub-lists
23
Codepublic static void mergeSort(int[] arr){ int[] temp = new int[arr.length]; msort(arr, temp, 0, arr.length);}
private static void msort(int[] arr, int[] temp, int left, int right){ // continue only if the sub-array has more than 1 element if ((left + 1) < right) { int mid = (right + left)/2; msort(arr, temp, left, mid); msort(arr, temp, mid, right); merge(arr, temp, left, mid, right); }} // end of msort()
O(n)
see MergeSort.java
merge
Tracing msort()
Merging two sorted arrays
20
13
7
2
12
11
9
1
1
20
13
7
2
12
11
9
2
20
13
7
12
11
9
7
20
13
12
11
9
9
20
13
12
11
11
20
13
12
12
Time = one pass through each array = O(n) to merge a total of n elements (linear time).
private static void merge(int[] arr, int[] temp, int left, int mid, int right) { // are the two sub-arrays already in sorted order? if (arr[mid-1] <= arr[mid]) return;
int indexA = left; // to scan 1st sub-array int indexB = mid; // to scan 2nd sub-array int i = left; // for moving over temp array
// compare arr[indexA] and arr[indexB]; copy the smaller to temp while ((indexA < mid) && (indexB < right)) { if (arr[indexA] < arr[indexB]) temp[i++] = arr[indexA++]; // copy and move idxs else temp[i++] = arr[indexB++]; } :
Contest Algorithms: 4. Backtracking
39
: // copy the tail of the sub-array that is not finished while (indexA < mid) temp[i++] = arr[indexA++];
while (indexB < right) temp[i++] = arr[indexB++];
// copy from temp back to arr for (int j = left; j < right; j++) arr[j] = temp[j]; } // end of merge()
Contest Algorithms: 4. Backtracking
40
public static void main (String[] args){ int[] arr = {18, 3, 5, 23, 4, 17, 2, 16, 19}; System.out.println("Unsorted array: " + Arrays.toString(arr));
mergeSort(arr); System.out.println("Sorted array: " + Arrays.toString(arr));
Integer[] intArr = {18, 3, 5, 23, 4, 17, 2, 16, 19}; Arrays.sort(intArr); // quicksort System.out.println("Sorted array: " + Arrays.toString(intArr));} // end of main()
Using Two Sorts
Contest Algorithms: 4. Backtracking
41