package com.interview.leetcode.binarysearch; /** * Created_By: stefanie * Date: 14-11-14 * Time: 下午4:27 * * Searching in array is a very typical algorithm, return its index if exist, return -1 if not found. * The condition of binarysearch can be divided as following cases: * each case will have implementations **L as Loop version and **R as Recursion version. * * Sorted or Partial Sorted * 1. binarysearch given number in sorted array, {@link SearchingSortedArray} * 2. binarysearch first/last/range appearance of a given number in a sorted array with duplication. {@link SearchingSortedArrayWithDuplication} * 3. binarysearch min/max/target in a given sorted rotated array. {@link SearchingRotatedArray} * min: array[mid] < array[mid - 1] indicate mid is min * else array[mid] >= array[high] min is in the right part, otherwise in left part * max: array[mid] > array[mid + 1] indicate mid is max * else array[mid] >= array[low] max is in the right part, otherwise in left part * find: get mid, if array[mid] == target return mid; * if(target < array[mid]) should search in left, but if array[mid] >= array[low] && target < array[low] (low ~ mid is increasing and target is smaller than low) binarysearch in right * if(target > array[mid]) should search in right, but if array[mid] <= array[high] && target > array[high] (mid ~ high is increasing and target is larger than low), binarysearch in left. * * 4. binarysearch min/max/target in a given sorted rotated array with duplication. {@link com.interview.leetcode.binarysearch.SearchingRotatedArrayWithDuplication} * basically have the same methodology as 3, but when have duplication, need check mid/low/high * if array[mid] == array[low] == array[high], can decide left or right, just move as usual: * min/max, low++ * find: if(target < array[mid]) low++, if(target > array[mid]) high--; * 5. binarysearch min/target in an array first decrease than increase {@link SearchingVArray} * min: array[mid-1] > array[mid] && array[mid+1] > array[mid] * if array[mid-1] < array[mid] -> mid in increasing part, and search min in low ~ mid-1. * if array[mid+1] < array[mid] -> mid in decreasing part, and search min in high ~ mid + 1; * if array[mid+1] == array[mid] == array[mid-1], can decide which part to search, low++; * find: get mid, * if array[mid] == target return mid; * if target < array[mid] * if array[mid-1] > array[mid] && array[mid+1] > array[mid], mid is min, so return -1; * if array[mid-1] < array[mid] -> mid in increasing part, and search min in low ~ mid-1. * if array[mid+1] < array[mid] -> mid in decreasing part, and search min in high ~ mid + 1; * if array[mid+1] == array[mid] == array[mid-1], can decide which part to search, low++; * if target > array[mid], need search left part if array[low] > target and right part if array[high] > target * 6. binarysearch merged k-th element in two sorted array. {@link SearchTwoSortedArray} * tracking the low element in a and b, if no element in a or b, return low + k - 1 * if k = 1, return min(a_low, b_low) * get half-k-th elements in A and B, if out of range, assign as Integer.MAX_VALUE * if half-k-th elements in A < B's, elements before half-k-th element in A belongs to topK, otherwise half-k-th element in B belongs topK. * so every time, it reduce K to a half size ( find half-k element belongs to topK) * continue binarysearch for k - half. * * Unsorted Array * 1. binarysearch given number in unsorted array. {@link SearchingUnsortedArray} * quick select, find a pivot, if array[pivot] == target, return true, else partition the array using the pivot. * if target < array[pivot] binarysearch in low ~ pivot - 1 * else binarysearch in pivot + 1 ~ high * 2. binarysearch K-th min/max element * quick select, find a pivot, partition use this pivot, if right place of pivot is k, return array[pivot] * if(index > k), search k in low, pivot - 1; * if(index < k), search k in pivot + 1, high; * notice index is the offset in whole array, so when index < k, still search k not k - index !important * * Tricks: * 1. in sorted array, use sorted feature to search half part of array * based on the relation of low, high, mid, target for rotated array * based on the relation of mid, mid - 1, mid + 1 for V array * 2. when the criteria is broken since array have duplication, array[mid] = array[low] = array[high] or array[mid] = array[mid-1] = array[mid+1] * just do low++ or high-- to find a new mid * 3. In unsorted array, using pivot to partition and search in one half. O(lgn) * */ public class Searching { }