目录
704.二分查找
- 使用前提:有序数组
- 循环不变量规则
- 注意区间的定义,不同写法对应代码不同
- 写法一:左闭右闭
- 写法二:左闭右开
var search = function(nums, target) {
let mid, left = 0, right = nums.length - 1;
while (left <= right) {
mid = left + Math.floor((right - left) / 2); // 注意一下这里的floor
if (nums[mid] > target) {
right = mid - 1; // 去左区间寻找
} else if (nums[mid] < target) {
left = mid + 1; // 去右区间寻找
} else {
return mid;
}
}
return -1;
};
35.搜索插入位置
- 方法一:暴力(O(n))
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); i++) {
if (nums[i] >= target) {
return i;
}
}
return nums.size();
}
};
- 方法二:二分
- 只要是有序数组,都可以看看能否使用二分法
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int i = 0;
int j = nums.size() - 1;
while (i <= j) {
int t = (i + j) / 2;
if (nums[t] == target) {
return t;
}
else if (nums[t] < target) {
i = t + 1;
}
else j = t - 1;
}
return i;
}
};
34.在排序数组中查找元素的第一个和最后一个位置
讨论三种情况:
- 情况一:target在数组范围之外
- 情况二:target在数组范围中,且数组中不存在target
- 情况三:target在数组范围中,且数组中存在target
接下来用二分法分别查询左右边界
注意:计算出来的左右边界是不包含target的左右边界,因此需将左边界+1,右边界-1得到最后结果
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int i = leftSearch(nums, target);
int j = rightSearch(nums, target);
if (i == -2 || j == -2) return vector<int>{-1,-1};
else if (j - i > 1) return vector<int>{i + 1, j - 1};
else return vector<int>{-1,-1};
}
private:
int leftSearch(vector<int> &nums, int t) {
int i = 0, j = nums.size() - 1;
int mid, leftRange = -2;
while (i <= j) {
mid = i + (j - i) / 2;
if (nums[mid] < t) {
i = mid + 1;
}
// 当nums[mid] >= t时 左边界一定位于nums[mid]的左侧
// 查找[i,mid-1]
else {
j = mid - 1;
leftRange = j;
}
}
return leftRange;
}
int rightSearch(vector<int> &nums, int t) {
int i = 0, j = nums.size() - 1;
int mid, rightRange = -2;
while (i <= j) {
mid = i + (j - i) / 2;
// 当nums[mid] <= t时 右边界一定位于nums[mid]的右侧
// 查找[mid+1,j]
if (nums[mid] <= t) {
i = mid + 1;
rightRange = i;
}
else {
j = mid - 1;
}
}
return rightRange;
}
};
69.x 的平方根
- 主要是需要注意到相乘后的数据可能超出int范围
- int的取值范围为-2147483648 ~ 2147483647(2E9,2^31-1)
- long long的取值范围 -9223372036854775808 ~ 9223372036854775807(9E18,2^63-1)
class Solution {
public:
int mySqrt(int x) {
int i = 0;
int j = x;
while (i <= j) {
int t = i + (j - i) / 2;
if ((long long)t * t == x) return t;
else if ((long long)t * t < x) {
i = t + 1;
}
else {
j = t - 1;
}
}
return j;
}
};
367.有效的完全平方数
- 和上一题相同思路
class Solution {
public:
bool isPerfectSquare(int num) {
int i = 0;
int j = num;
while (i <= j) {
int t = i + (j - i) / 2;
if ((long long)t * t == num) {
return true;
}
else if ((long long)t * t < num) {
i = t + 1;
}
else {
j = t - 1;
}
}
return false;
}
};