704.二分查找
题目链接:一刷总结
35.搜索插入位置
解题思路
这道题目的难点在于target不在数组中时,该如何返回正确的下标。如果直接用暴力循环,因为数组是升序的,因此只需要遍历到第一个nums[i]>=target的位置即为插入位置。
使用二分法如何确定呢,先假设两个极端情况(这里使用左闭右闭的方式实现):
1.如果数组中所有元素都大于target,那么left保持为0不变,right最终为-1。
2.如果数组中所有元素都小于target,那么right保持为n-1不变,left最终为n。
可以发现,这两种情况中,最终left的值即为插入下标,这是不是巧合呢?实际上不是。给定一个任意升序数组,只要其中有一个元素的值大于target,就一定能找到一个区间[left, right]满足区间中的元素都大于target,这就回到了上面说的情况2。
解法
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0, right = nums.size()-1;
while(left <= right){
int mid = left + (right - left) / 2;
if(target == nums[mid])
return mid;
else if(target > nums[mid])
left = mid + 1;
else
right = mid - 1;
}
return left;
}
};
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
34.在排序数组中查找元素的第一个和最后一个位置
解题思路
这里实际上就是怎么通过二分法确定元素区间的左边界和右边界,通过上一题的分析过程可知,如果target总是比nums[mid]小,那么right会一直左移而left不变,最终left即为插入位置。但是这道题会出现target==nums[mid]的情况,岂不是就不能让right 移动到预期的位置?实际上,可以调整条件为nums[mid]>=target,这样,就能按照刚刚的想法,使得right移动到预期的位置,这下目标元素区间的左边界就是最后得到的left了。
那右边界呢,再来一次二分,将这个=的条件放到更新left的地方,这样就会是left移动到预期的位置,最后得到的right即为目标元素区间右边界。实际代码中,还需要注意一些边界条件的处理,看下方的解法可知。
解法
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int n = nums.size();
if(n<0)
return {-1, -1};
int left1 = 0, right1 = n-1;
while(left1 <= right1) {
int mid = left1 + (right1 - left1) / 2;
if(nums[mid] >= target)
right1 = mid - 1;
else
left1 = mid + 1;
}
if(left1 > n-1 || nums[left1]!=target)
return {-1, -1};
int left2 = 0, right2 = n-1;
while(left2 <= right2) {
int mid = left2 + (right2 - left2) / 2;
if(nums[mid] <= target)
left2 = mid + 1;
else
right2 = mid - 1;
}
return {left1, right2};
}
};
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
69.x 的平方根
题目链接:Leetcode
解题思路
比较基础的一道题,不过其中还是有细节值得学习的。与前面的题目不同的是,这道题需要在二分的过程中记录期间计算的到的值,本题中即为mid。题目要求的是向下取整,因此在每次更新left的时候才进行mid的记录,同理,如果下次要求的是向上取整,在每次更新right的时候更新mid的记录即可。
解法
class Solution {
public:
int mySqrt(int x) {
if(x==0 || x==1)
return x;
long long left = 1, right = x;
long long result;
while(left < right) {
long long mid = left + (right - left) / 2;
long long square = mid * mid;
if(square == x)
return mid;
else if(square > x)
right = mid;
else {
result = mid;
left = mid + 1;
}
}
return result;
}
};
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
367.有效的完全平方数
题目链接:Leetcode
解法
class Solution {
public:
int mySqrt(int x) {
if(x==0 || x==1)
return x;
long long left = 1, right = x;
long long result;
while(left < right) {
long long mid = left + (right - left) / 2;
long long square = mid * mid;
if(square == x)
return mid;
else if(square > x)
right = mid;
else {
result = mid;
left = mid + 1;
}
}
return result;
}
};
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
&spm=1001.2101.3001.5002&articleId=156265405&d=1&t=3&u=a59292500a2543f49cb4485384085e1c)
659

被折叠的 条评论
为什么被折叠?



