二分查找

Posted 张乐乐章

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找相关的知识,希望对你有一定的参考价值。

https://labuladong.gitbook.io/algo/mu-lu-ye/er-fen-cha-zhao-xiang-jie

 1 int binary_search(int[] nums, int target) {
 2     int left = 0, right = nums.length - 1; 
 3     while(left <= right) {
 4         int mid = left + (right - left) / 2;
 5         if (nums[mid] < target) {
 6             left = mid + 1;
 7         } else if (nums[mid] > target) {
 8             right = mid - 1; 
 9         } else if(nums[mid] == target) {
10             // 直接返回
11             return mid;
12         }
13     }
14     // 直接返回
15     return -1;
16 }
17 
18 int left_bound(int[] nums, int target) {
19     int left = 0, right = nums.length - 1;
20     while (left <= right) {
21         int mid = left + (right - left) / 2;
22         if (nums[mid] < target) {
23             left = mid + 1;
24         } else if (nums[mid] > target) {
25             right = mid - 1;
26         } else if (nums[mid] == target) {
27             // 别返回,锁定左侧边界
28             right = mid - 1;
29         }
30     }
31     // 最后要检查 left 越界的情况
32     if (left >= nums.length || nums[left] != target)
33         return -1;
34     return left;
35 }
36 
37 
38 int right_bound(int[] nums, int target) {
39     int left = 0, right = nums.length - 1;
40     while (left <= right) {
41         int mid = left + (right - left) / 2;
42         if (nums[mid] < target) {
43             left = mid + 1;
44         } else if (nums[mid] > target) {
45             right = mid - 1;
46         } else if (nums[mid] == target) {
47             // 别返回,锁定右侧边界
48             left = mid + 1;
49         }
50     }
51     // 最后要检查 right 越界的情况
52     if (right < 0 || nums[right] != target)
53         return -1;
54     return right;
55 }

 

 

 

https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

 

278. First Bad Version(二分查找)

35. Search Insert Position(二分查找)

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

解法:

 1 class Solution {
 2 public:
 3     int searchInsert(vector<int>& nums, int target) {
 4         int low = 0;
 5         int high = nums.size() - 1;
 6         while(low <= high) {
 7             int mid = low + (high - low)/2;
 8             if (nums[mid] < target) low = mid + 1;
 9             else if (nums[mid] > target) high = mid - 1;
10             else if (nums[mid] == target) return mid;
11         }
12         return low;
13     }
14 };

 

 

33. Search in Rotated Sorted Array(二分查找)  旋转数组的二分查找

 1 class Solution {
 2 public:
 3     int search(vector<int>& nums, int target) {
 4         int low = 0;
 5         int high = nums.size() - 1;
 6         while(low <= high) {
 7             int mid = low + (high - low)/2;
 8             if (nums[mid] == target) return mid;
 9             if (nums[low] <= nums[mid]) { // the left is sorted
10                 if (nums[low] <= target && target <= nums[mid]) { // target is in the left
11                     high = mid - 1; // go to the left to search
12                 } else { // target is in hte right
13                     low = mid + 1; // go to the right to search
14                 }
15             } else { // the right is sorted
16                 if (nums[mid] <= target && target <= nums[high]) { // target is in the right
17                     low = mid + 1; //go to the right to search 
18                 } else { // target is in the left
19                     high = mid - 1; //go to the left to search 
20                 }
21             }
22         }
23         return -1;
24     }
25 };

 

81. Search in Rotated Sorted Array II

旋转数组中有重复的数

给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。

 需要判断下相等的情况

 1 class Solution {
 2 public:
 3     int search(vector<int>& nums, int target) {
 4         int low = 0;
 5         int high = nums.size() - 1;
 6         while(low <= high) {
 7             int mid = low + (high - low)/2;
 8             if (nums[mid] == target) return true;
 9             if (nums[low] == nums[mid]) low++;
10             else if (nums[low] < nums[mid]) { // the left is sorted
11                 if (nums[low] <= target && target <= nums[mid]) { // target is in the left
12                     high = mid - 1; // go to the left to search
13                 } else { // target is in hte right
14                     low = mid + 1; // go to the right to search
15                 }
16             } else { // the right is sorted
17                 if (nums[mid] <= target && target <= nums[high]) { // target is in the right
18                     low = mid + 1; //go to the right to search
19                 } else { // target is in the left
20                     high = mid - 1; //go to the left to search
21                 }
22             }
23         }
24         return false;
25     }
26 };

 

 

153. Find Minimum in Rotated Sorted Array(二分查找)

旋转数组 寻找最小值

解法:寻找

 1 class Solution {
 2 public:
 3     int findMin(vector<int>& nums) {
 4         int low = 0;
 5         int high = nums.size() - 1;
 6         while(low < high) {
 7             int mid = low + (high - low ) / 2;
 8             if(nums[mid] < nums[high]) {
 9                 high = mid;
10             } else if(nums[mid] > nums[high]) {
11                 low = mid + 1;
12             } else if (nums[mid] == nums[high]) {
13                 low = mid + 1 ;
14             }
15         }
16         return nums[low];
17     }
18 };

 

 

 

 

 154. Find Minimum in Rotated Sorted Array II (旋转重复数组二分查找最小值)

 

class Solution {
public:
    int findMin(vector<int>& nums) {
        int low = 0;
        int high = nums.size() - 1;
        while(low < high) {
            int mid = low + (high - low ) / 2;
            if(nums[mid] < nums[high]) {
                high = mid;
            } else if (nums[mid] > nums[high]){
                low = mid + 1;
            } else { // nums[mid] = nums[high] ,并不能确定nums[mid] 究竟在最小值的左侧还是右侧,因此我们不能莽撞地忽略某一部分的元素.
                high--;
            }
        }
        return nums[low];
    }
};

 

 

 162. Find Peak Element(二分查找, 注意二分缩减范围的条件)

 

 1 class Solution {
 2 public:
 3     int findPeakElement(vector<int>& nums) {
 4         int low = 0;
 5         int high = nums.size() - 1;
 6         while(low < high) {
 7             int mid = low + (high - low ) /2;
 8             if (nums[mid] < nums[mid+1]) {
 9                 low = mid + 1;
10             } else {
11                 high = mid;
12             }
13         }
14         return low;
15     }
16 };

 

  

 
374 Guess Number Higher or Lower (标准二分查找)
 
 1 class Solution {
 2 public:
 3     int guessNumber(int n) {
 4         int low = 1;
 5         int high = n;
 6         while(low < high) {
 7             int mid = low + (high - low) /2;
 8             if (guess(mid) == 0) return mid;
 9             else if(guess(mid) == 1) low = mid + 1;
10             else if(guess(mid) == -1) high = mid;
11         }
12         return low;
13     }
14 };

34. Search for a Range (两次二分查找) 

 1 class Solution {
 2 public:
 3     //两次二分
 4     vector<int> searchRange(vector<int>& nums, int target) {
 5         //首先判断空集
 6         if (nums.size()==0){
 7             return {-1,-1};
 8         }
 9         //第一次二分,求出第一个>=target的元素
10         int a1=0;
11         int low = 0;
12         int high = nums.size() - 1;
13         while(low<high){
14             int mid = low +(high-low)/2;
15             if (nums[mid]>=target){
16                 high = mid;
17             }else{
18                 low = mid+1;
19             }
20         }
21         a1 = low;
22         //求出的low可以是0~nums.size()
23         //如果求出的low是num.size()肯定为-1
24         //如果求出的low位置的元素不是target,表明该集合没有target,直接返回[-1,-1]
25         if(low==nums.size()||nums[low]!=target){
26             return {-1,-1};
27         }
28         
29         //如果left1求出来后,在[0,num.size()-1]的范围内,且num[left1]==target,那么就继续第二次二分求第一个>target的值
30 
31         high = nums.size();// 为了处理 【1】1 、【2,2】2 这种情况
32         while(low<high){
33             int mid = low+(high-low)/2;
34             if (nums[mid]>target){
35                 high = mid;
36             }else{
37                 low = mid+1;
38             }
39         }
40         //经历过第一个二分没返回[-1,-1],表明target肯定在数组里
41         //所以求出的left2可以是1~nums.size(),这时候left2-1肯定是最后一个=target的值的下标
42         return {a1,low-1};
43     }
44 };

 

 69. Sqrt(x)(二分查找)

 

class Solution {
public:
    int mySqrt(int x) {
        if (x <=1) return x;
        int low = 0;
        int high = x ;
        while(low <= high) {
            int mid = low + (high-low)/2;
            if (x/mid > mid) {
                low = mid + 1;
            } else if(x/mid < mid) {
                high = mid - 1;
            } else {
                return mid;
            }
        }
        // 正常二分法,如果没找到,返回的是大于target 的位置。此题需要返回小于target的位置。8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
        return low - 1;
    }
};

 

74. Search a 2D Matrix(两次二分查找,剑指offer 1)

 

 1 class Solution {
 2 public:
 3     bool searchMatrix(vector<vector<int>>& matrix, int target) {
 4         // 先根据最后一列二分查找,确定 target 在哪一行。
 5         int n = matrix.size(); //3
 6         int m = matrix[0].size();//4
 7         int low = 0;
 8         int high = n -1 ;
 9         while(low < high) {
10             int mid = low + (high - low) / 2;
11             if (matrix[mid][m-1] < target) {
12                 low = mid + 1;
13             } else if(matrix[mid][m-1] > target) {
14                 high = mid ;
15             } else {
16                 return true;
17             }
18         }
19         // low is the target 行
20         int wanted_row = low;
21         low = 0;
22         high = m - 1 ;
23 
24         while(low < high) {
25             int mid = low + (high - low) /2;
26             if(matrix[wanted_row][mid] < target) {
27                 low = mid + 1;
28             } else if (matrix[wanted_row][mid] > target) {
29                 high = mid ;
30             } else {
31                 return true;
32             }
33         }
34         return matrix[wanted_row][low] == target;
35     }
36 };

 

 

 

 
 
 
 
 
 

以上是关于二分查找的主要内容,如果未能解决你的问题,请参考以下文章

java 二分查找法

代码题(12)— 二分查找

二分查找代码

PHP实现二分查找算法(代码详解)

「算法笔记」一文摸秃二分查找

C语言二分查找