Contest Algorithms January 2016 Pseudo-code for divide and conquer, and three examples (binary exponentiation, binary search, and mergesort). 5. Divide & Conquer 1Contest 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 solve subproblem 2 of size n /2 a solution to subproblem 1 a solution to the original problem solve a problem of size n a recursive algorithm combine solutions solve subproblem 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 : x n 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 x 2 return x * p * p; } else { // n even long p = pow(x, n/2); return p * p; } } // end of pow() see Power.java
Java interprets all numeral literals as 32-bit integers. e.g. long x = ; // will give "integer number too large" error int range: to ( ) If you want to write something bigger than a 32-bit integer, use the suffix L: e.g. long x = L ; // accepted Writing long numbers Contest Algorithms: 4. Backtracking6
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. Backtracking7
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. Backtracking8
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. Backtracking9
10
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. Backtracking11
Contest Algorithms: 4. Backtracking12
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 Contest Algorithms: 4. Backtracking13
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 As implemented in Java by Arrays. binarySearch()
Example Example: Find Find an element in a sorted array: 1.Divide: Check middle element. 2.Conquer: Recursively search 1 subarray. 3.Combine: Trivial.
Example: Find Find an element in a sorted array: 1.Divide: Check middle element. 2.Conquer: Recursively search 1 subarray. 3.Combine: Trivial.
Example: Find Find an element in a sorted array: 1.Divide: Check middle element. 2.Conquer: Recursively search 1 subarray. 3.Combine: Trivial.
Example: Find 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
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
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 Contest Algorithms: 4. Backtracking21 Index pos of 10: 5 Index pos of 22: -11 Index pos of 10: 5 Index 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 Code public 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 The merge() function
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays
Merging two sorted arrays Time = one pass through each array = (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++]; } :
: // 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. Backtracking39
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. Backtracking40
Contest Algorithms: 4. Backtracking41