704.二分查找
写二分查找时需要格外注意搜索区间的定义,我在第一次写时因为这一点导致代码陷入了死循环。
class solution1 {
int binarySearch(vector<int>& nums, int target)
{
int left = 0;
int right = nums.size() - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (nums[mid] == target)
{
return mid;
}
else if (nums[mid] > target)//target<nums[mid]时,target下标在[begin,mid-1]
{
right = mid - 1;/*注意 这里的right不是mid而是mid-1,因为如果是right=mid,当right-left=1的时候会陷入死循环*/
}
else//target>nums[mid]时,target下标在[mid+1,end]
{
left = mid + 1;/*注意:这里的begin不是mid而是mid+1*/
}
}
return -1;
}
};
总结:因为int类型的除法会直接舍去小数,这会导致一个问题,即我在后面每进行一次比较就习惯性的将区间界限值直接修改为mid(二分查找的思想就是这样的),但是在区间上下界差为1的情况下如果还未找到元素,程序将会陷入死循环。这也是初学者常犯的错误。
例如:left = 22;right=23;mid=22;
此时如果还未找到,那么无论执行mid = (left+right)/2多少次,mid都为22,陷入了死循环。
此外,在我们判断出除nums[mid]>target的情况下,我们就可以判断出target在[left,mid-1]中而不是[left,mid],nums[mid]已经判断过了,直接从比它前面一个的位置开始搜索即可。(小于也是同理,这里就不过多赘述了)
35.搜索插入位置
这一题只需要在上面的基础上增加一个如果没有找到指定数据,就返回应该插入的数据而不是返回-1
//在没有找到的情况下,target的插入位置一定子mid的左边或者右边
if (target > nums[mid])
{
return mid + 1;
}
else
{
return mid;
}
34.查找指定元素起始位置
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
vector<int> array = { -1,-1 };
int mid;
while ((array[0] == -1 || array[1] == -1) && left <= right)
{
mid = (left + right) / 2;
if (nums[mid] == target)
{
array[0] = array[1] = mid;
while ((array[0] - 1) >= 0&&nums[array[0] - 1] == target)
{
array[0]--;
}
while ((array[1] + 1) <= (nums.size() - 1)&&nums[array[1] + 1] == target )
{
array[1]++;
}
return array;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return array;
}
};
总结:这一题要注意数组越界访问,操作下标时要注意nums[-1]或nums[size]的情况出现,因此,找起始位置的那个while循环的循环条件中,array[0] - 1) >= 0要放在nums[array[0]-1]==target之前。
剩下两题 找平方根和判断完全平方数
int mySqrt(int x) {
int left = 0;
int right = x;
long long mid;
while (left <= right)
{
mid = (left + right) / 2;
if (mid*mid<=x&&(mid+1)*(mid+1)>x)
{
return mid;
}
else if ((mid + 1) * (mid + 1) <= x)
{
left = mid + 1;
}
else {
right = mid - 1;
}
}
return -1;
}
bool isSqrt(int x) {
int left = 0;
int right = x;
long long mid;
while (left <= right)
{
mid = (left + right) / 2;
if (mid * mid <= x && (mid + 1) * (mid + 1) > x)
{
if (mid * mid == x)
{
return true;
}
else {
return false;
}
}
else if ((mid + 1) * (mid + 1) <= x)
{
left = mid + 1;
}
else {
right = mid - 1;
}
}
return -1;
}