二分查找详解

Posted by Sutdown on August 21, 2025

二分查找详解

写法一:

35. 搜索插入位置 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	int searchInsert(vector<int>& nums, int target) {
        int left = 0, right = (int)nums.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == target) return mid;
            if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
	
	int searchInsert(vector<int>& nums, int target) {
        // 返回第一个值大于等于target的下标
        int left = 0, right = (int)nums.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] >= target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left; // left右侧的位置都大于等于left,left左侧位置都小于left
    }

如果数组为[1,3,5,6],target=2;

left = 0, right = 3(均为位置)

第一轮 mid=1, left=0, right=0;

第二轮 mid=0, left=1,right=1;

总结:当target不在数组时,需要返回按顺序插入的位置,也就是第一个比target大的位置。因此返回left是最佳方案,right只会是比target小的第一个位置。

写法二:

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
	vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.size() == 0)
            return vector<int>{-1, -1};

        int l1 = -1, l2 = -1;
        int left = 0, right = (int)nums.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] >= target) { // 找出第一个大于等于target的下标
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        if (left < nums.size() && nums[left] == target)
            l1 = left;

        left = 0, right = (int)nums.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] <= target) { // 找出第一个小于等于target的下标
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        if (right < nums.size() && nums[right] == target)
            l2 = right;

        return vector<int>{l1, l2};
    }

进阶:寻找峰值

162. 寻找峰值 - 力扣(LeetCode)

1
2
3
4
5
6
7
8
9
10
11
12
	int findPeakElement(vector<int>& nums) {
        int l = 0, r = nums.size() - 1;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (nums[mid] > nums[mid + 1]) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }