本文总结了一些二分查找的变形,其中大部分来自 leetcode
1. (leetcode 33) Search in Rotated Sorted Array
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
public int search(int[] nums, int key) { int lo = 0,hi = nums.length - 1; while(lo <= hi){ int mid = lo + (hi - lo)/2; if(nums[mid] == key) return mid; if(nums[mid] < nums[hi]){//右半部分有序 if(nums[mid] < key && key <= nums[hi]){ lo = mid + 1; //key 落在有序部分 }else{ //否则 key 落在无序部分 hi = mid -1; } }else{ //左半部分有序 if(nums[lo] <= key && key < nums[mid]){ hi = mid -1; //key 落在有序部分 }else{ //否则 key 落在无序部分 lo = mid + 1; } } } return -1; }
2. (leetcode 81) Search in Rotated Sorted Array II
(i.e. 1 2 4 4 4 4 4 might become 4 4 4 1 2 4 4 ).
//关于最后 nums[mid] == nums [hi] 的情况 //1 2 1 1 1 //l m h -> hi--; //1 2 1 1 1 //l m h public boolean search(int[] nums, int target) { if(null == nums || nums.length < 0) return false; int lo = 0,hi = nums.length - 1; while(lo <= hi){ int mid = lo + (hi - lo)/2; // get it if(nums[mid] == target) return true; //找到有序的部分进行查找 if(nums[mid] < nums[hi]){// 后半部分有序 if(nums[mid] < target && target <= nums[hi]){ lo = mid + 1; }else{ hi = mid - 1; } }else if(nums[mid] > nums[hi]){// 前半部分有序 if(nums[lo] <= target && target < nums[mid]){ hi = mid - 1; } else{ lo = mid + 1; } }else{ //nums[mid] == nums[hi] hi -- ; } } return false; }
3. Find Minimum in Rotated Sorted Array
旋转的数组中,找到最小的数
若 nums[mid] > nums[hi] min 落在 [mid+1, hi]
若 nums[mid] < nums[hi] min 落在 [0, mid] 上
public int findMin(int[] nums) { int lo = 0,hi = nums.length - 1; while( lo < hi){ int mid = lo + (hi - lo)/2 ; //mid > hi,min in [mid+1,hi] if(nums[mid] > nums[hi]){ lo = mid + 1; } //mid < hi, min in [0,mid] if(nums[mid] < nums[hi]){ hi = mid; } } return nums[lo]; }
4. Find Minimum in Rotated Sorted Array II
跟上次的题目一样,只不过带重复的,与题目 1 -> 2 的思路完全一样
若 nums[mid] > nums[hi] min 落在 [mid+1, hi]
若 nums[mid] < nums[hi] min 落在 [0, mid] 上
若 nums[mid] == nums[hi] 则 hi--之后做进一步判断
public int findMin(int[] nums) { int lo = 0, hi = nums.length -1; while(lo < hi){ int mid = lo + (hi - lo)/2; if(nums[mid] > nums[hi]){ lo = mid + 1; }else if(nums[mid] < nums[hi]){ hi = mid; }else{ hi--; } } return nums[lo]; }
5. Find Peak Element (leetcode)
public int Peak(int nums[]) { int lo = 0, hi = nums.length - 1; while(lo < hi) { int m1 = lo + (hi - lo) / 2; int m2 = m1 + 1; if(nums[m1] < nums[m2]){ lo = m2; }else{ hi = m1; } } return nums[lo]; }