第一题:
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while(left <= right){int mid = (right - left) / 2 + left;int num = nums[mid];if (num == target) {return mid;} else if (num > target) {right = mid - 1;} else {left = mid + 1;}}return -1;}
};
第一题没什么细节,用笔在纸上画一下模拟一下即可
第二题:
这一道题相对其他题比较抽象,具体体现在其最后一个位置不好找,因为在编译的时候,计算mid时系统会自动向下取整,因此在处理左端点时可以向下取整得到,处理又端点时需要向上取整,同时要注意数据的溢出,这里是如何处理的。
class Solution {
public:vector<int> searchRange(vector<int>& nums, int target){if (nums.size() == 0) return{ -1,-1 };int begin = 0;int left = 0, right = nums.size() - 1, mid;while (left < right){mid = left + (right - left) / 2;if (nums[mid] < target)left = mid + 1;elseright = mid;}if (target != nums[right]) return{ -1,-1 };elsebegin = left;left = 0, right = nums.size() - 1;while (left < right){mid = left + (right - left + 1) / 2;if (nums[mid] <= target)left = mid;elseright = mid-1;}return{ begin,right };}
};
我绝得这个题最关键的步骤就是,nums[mid]与target是否取等,在求开始位置的时候,不用取等,原因是else成立条件为>=那么right所指向的未必是最右边的那个元素,因为可能有重复元素,对于求最后位置时,else条件为>的目的是,使得right所指向的目标元素为最后的位置。
第三题:
class Solution {
public:int searchInsert(vector<int>& nums, int target) {int n = nums.size();int l=0,r=n-1;while(l<=r){int mid=l+(r-l)/2;if(nums[mid]<target)l=mid+1;else r=mid-1;}return l;}
};
- 判断中间位置的值
nums[mid]
与目标值target
的大小关系:- 若
nums[mid] < target
,说明目标值在右半部分,将l
更新为mid+1
。 - 若
nums[mid] >= target
,说明目标值在左半部分或者等于中间值,将r
更新为mid-1
。
- 若
- 循环结束后,返回
l
,即为目标值在数组中的插入位置
第四题:
整数平方根最小为1,最大为本身,因此左指针指在1,右指针指在r,防止mid*mid的值溢出,将数据类型设为long long 类型
在这个平方根求解算法中,向上取整(即计算中点时使用的 mid = l + (r - l + 1) / 2
而不是 mid = l + (r - l) / 2
)的主要原因是为了确保二分查找过程能够正确地收敛,特别是在处理左右边界相邻但还未找到确切平方根整数值的情况下。
这个细节主要影响的是当左边界(l
)和右边界(r
)相邻时的行为。常规的二分查找中点计算(向下取整)可能会导致在某些情况下循环不能正确终止,进而错过正确答案。具体到这个问题:
第五题:
class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int l=1,r=arr.size()-2,mid;while(l<r){mid=l+(r-l+1)/2;if(arr[mid]<arr[mid-1])r=mid-1;elsel=mid;}return l;}
};
山脉即大于左右两边的山,暴力也可求解
class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int n = arr.size();// 遍历数组内每⼀个元素,直到找到峰顶for (int i = 1; i < n - 1; i++)// 峰顶满⾜的条件if (arr[i] > arr[i - 1] && arr[i] > arr[i + 1])return i;// 为了处理 oj 需要控制所有路径都有返回值return -1;}
}