69.x的平方根
题解:对于0,1来说平方根为自身,故从[0,x]进行搜索符合条件的数。采用二分查找的方法,找最大的平方小于等于x的值。如果采用向下取整取中间值,则会出现死循环以6为例。故应采用向上取整取中间值。在mid * mid > x的情况下,mid值不在取值区间内,因此right = mid - 1。而小于时仍在取值范围内应该保留 left = mid;代码如下:
class Solution {
public:
int mySqrt(int x) {
long left = 0, right = x;
while(left < right)
{
long mid = (left + right + 1) >> 1;
if(mid == x / mid) return mid;
else if(mid < x / mid) left = mid;
else right = mid - 1;
}
return left;
}
};
34.在排序数组中查找元素的第一个和最后一个位置
题解:二分查找第一个位置的方法:向下取整,等号归右,左加一。最后一个位置的方法:向上取值,等号归左,右减一。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> a(2, -1);
if(nums.size() == 0)
return a;
int left = 0, right = nums.size() - 1;
while(left < right)
{
int mid = (left + right) >> 1;
if(nums[mid] >= target) right = mid;
else left = mid + 1;
}
if(nums[right] != target)
{
return a;
}
a[0] = right;
left = right;
right = nums.size() - 1;
while(left < right)
{
int mid = (left + right + 1) >> 1;
if(nums[mid] <= target) left = mid;
else right = mid - 1;
}
a[1] = right;
return a;
}
};
81.搜索旋转排序数组||
题解:二分的本质是二段性并非单调性。二段性即一部分大于某数,另一部分小于某数。等号不能重叠。对于本题来说,旋转会出现将相同元素分割的情况因此需要先预处理,使得数组满足二分的二段性。
class Solution {
public:
bool search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(right > left && nums[left] == nums[right])
right--;
if(right == left)
{
if(nums[0] == target)
return true;
else
return false;
}
while(left < right) //找到分割点
{
int mid = (left + right + 1) >> 1;
if(nums[mid] >= nums[0]) left = mid;
else right = mid - 1;
}
return find(nums,0, right, target) || find(nums, right+1, nums.size() - 1, target);
}
bool find(vector<int>& nums, int left, int right, int t)
{
while(left < right)
{
int mid = (left + right + 1) >> 1;
if(nums[mid] == t)
return true;
else if(nums[mid] < t)
left = mid + 1;
else right = mid - 1;
}
if(nums[right] == t)
return true;
else
return false;
}
};
540.有序数组中的单一元素
题解:对于由一对数组成的数组来说,第一个值的下标为偶数,第二个值的下表为奇数。当插入一个数之后,其左边的数组规律不变,右边与左边正好相反,因此采用二分法。当mid为偶数时,下一个数如果与其相等,则插入的数在右边,left = mid + 2;否则right = mid(包括mid本身)。当mid为奇数时,mid的值不可能为插入的数(单个数的下标一定是偶数),如果mid等于下一个值,则插入的数在左边,right = mid - 1,否则left = mid + 1。
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
if(nums.size() == 1)
return nums[0];
int left = 0, right = nums.size() - 1;
while(left < right)
{
int mid = (left + right) >> 1;
if(mid % 2 == 0)
{
if(nums[mid] == nums[mid + 1])
left = mid + 2;
else
right = mid;
}
else {
if(nums[mid] == nums[mid - 1])
left = mid + 1;
else
right = mid - 1;
}
}
return nums[right];
}
};