二分查找的流程:
1.确定二分的边界
2.编写二分的代码框架
3.设计一个check性质
4.判断一下区间如何更新
5.如果更新方式写的是l=mid,r=mid-1,那么就在算mid的时候+1
1 二分的模板:
bool check(int x) {/* ... */} // 检查x是否满足某种性质 2 //求第二个线段的起点 3 // 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用: 4 int bsearch_1(int l, int r) 5 { 6 while (l < r) 7 { 8 int mid = l + r >> 1; 9 if (check(mid)) r = mid; // check()判断mid是否满足性质 10 else l = mid + 1; 11 } 12 return l; 13 } 14 // 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
//求第一个线段的终点
15 int bsearch_2(int l, int r) 16 { 17 while (l < r) 18 { 19 int mid = l + r + 1 >> 1; 20 if (check(mid)) l = mid; 21 else r = mid - 1; 22 } 23 return l; 24 } 25 26
LEETCODE35.
class Solution { public int searchInsert(int[] nums, int target) { if(nums.length==0) return 0; if(target>nums[nums.length-1]) return nums.length; int r=nums.length-1; int l=0; while(l<r){ int mid=l+r>>1; if( nums[mid]>=target) r=mid; else l=mid+1; } return l; } }
1 class Solution { 2 public int mySqrt(int x) { 3 int l=0; int r=x; 4 while(l<r){ 5 int mid=l+r>>1; 6 if(mid<=x/mid) r=mid; 7 else l=mid+1; 8 } 9 return l; 10 } 11 }
1 class Solution { 2 public int[] searchRange(int[] nums, int target) { 3 if(nums.length==0) return new int[]{-1, -1}; 4 //先找出初始位置,nums[mid]>=target,也就是第二条线段的起点,用模板一 5 int l=0,r=nums.length-1; 6 while(l<r){ 7 int mid=l+r>>1; 8 if(nums[mid]>=target) r=mid; 9 else l=mid+1; 10 } 11 if(nums[r]!=target) return new int[]{-1, -1}; 12 //再找出终止位置,nums[mid]<=target,也就是第一条线段的终点,用模板二 13 int l1=0,r1=nums.length-1; 14 int start=l; 15 while(l1<r1){ 16 int mid=l1+r1+1/2; 17 if(nums[mid]<=target) l1=mid; 18 else r1=mid-1; 19 } 20 int end=r1; 21 return new int[]{start,end}; 22 } 23 }
1 class Solution { 2 public boolean searchMatrix(int[][] matrix, int target) { 3 //matrix[mid/m][mid%m]>=target,想找的就是第二条线段的起点,用模板一 4 if(matrix.length==0||matrix[0].length==0) return false; 5 int n=matrix.length; 6 int m=matrix[0].length; 7 int l=0;int r=m*n-1; 8 while(l<r){ 9 int mid=l+r>>1; 10 if(matrix[mid/m][mid%m]>=target) r=mid; 11 else l=mid+1; 12 } 13 return matrix[r/m][r%m]==target; 14 } 15 }
class Solution { public int findMin(int[] nums) { int l=0,r=nums.length-1; //一个y=x的函数切成两半,找到第二段线段的起点,用模板一 while(l<r){ int mid=l+r>>1; if(nums[mid]<=nums[nums.length-1]) r=mid; else l=mid+1; } return nums[l]; } }
1 /* The isBadVersion API is defined in the parent class VersionControl. 2 boolean isBadVersion(int version); */ 3 4 public class Solution extends VersionControl { 5 public int firstBadVersion(int n) { 6 int l=0,r=n; 7 //找第二个线段的起点,用模板一 8 while(l<r){ 9 int mid=l+(r-l)/2;//防止溢出 10 if(isBadVersion(mid)==true) r=mid; 11 else l=mid+1; 12 } 13 return l; 14 } 15 }
1 class Solution { 2 public int search(int[] nums, int target) { 3 //先确定在旋转后的函数的哪段,再对这一段进行二分 4 int n=nums.length; 5 int l=0; 6 int r=n-1; 7 if(n==0) return -1; 8 //找第二个线段的起点 9 while(l<r){ 10 int mid=l+r>>1; 11 if(nums[mid]<nums[n-1]) r=mid; 12 else l=mid+1; 13 } 14 if(target<=nums[n-1]) r=n-1; 15 else {l=0; r--;} 16 while(l<r){ 17 int mid=l+r>>1; 18 if(nums[mid]>=target) r=mid; 19 else l=mid+1; 20 } 21 if(nums[l]==target) return l; 22 return -1; 23 24 } 25 }
class Solution { public int search(int[] nums, int target) { int n = nums.length; if (n == 0) { return -1; } if (n == 1) { return nums[0] == target ? 0 : -1; } int l = 0, r = n - 1; while (l <= r) { int mid = (l + r) / 2; if (nums[mid] == target) { return mid; } if (nums[0] <= nums[mid]) { if (nums[0] <= target && target < nums[mid]) { r = mid - 1; } else { l = mid + 1; } } else { if (nums[mid] < target && target <= nums[n - 1]) { l = mid + 1; } else { r = mid - 1; } } } return -1; } }
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 int n = nums.length; 4 int l = 1, r = n - 1, ans = -1; 5 while (l <= r) { 6 int mid = (l + r) >> 1; 7 int cnt = 0; 8 for (int i = 0; i < n; ++i) { 9 if (nums[i] <= mid) { 10 cnt++; 11 } 12 } 13 if (cnt <= mid) { 14 l = mid + 1; 15 } else { 16 r = mid - 1; 17 ans = mid; 18 } 19 } 20 return ans; 21 22 23 } 24 }
1 class Solution { 2 public int hIndex(int[] citations) { 3 int n=citations.length; 4 int l=0; 5 int r=n ; 6 while(l<r){ 7 int mid=l+r+1>>1; 8 if(citations[n-mid]>=mid) l=mid; 9 else r=mid-1; 10 } 11 return r; 12 } 13 }