【数据结构与算法】LeetCode:二分查找
文章目录
- 二分查找
- 二分查找
- 搜索插入位置 (Hot 100)
- x 的平方根
- 搜索二维矩阵(Hot 100)
- 在排序数组中查找元素的第一个和最后一个位置 (Hot 100)
- 搜索旋转排序数组 (Hot 100)
- 寻找旋转排序数组中的最小值 (Hot 100)
二分查找
二分查找
二分查找
class Solution{
public:
int search(vector<int>& nums, int target){
// 设定左闭右闭的区间
int left = 0;
int right = nums.size() - 1;
while (left <= right){ // 闭区间查找,left == right依然有效,所以用<=
int middle = left + (right-left) / 2; // 中值索引
if (nums[middle] > target){
right = middle-1; // target在左边,更新右上限
}
else if (nums[middle] < target){
left = middle + 1; // target在右边,更新左上限
}
else{
return middle; // 找到target,返回下标
}
}
return -1;
}
};
搜索插入位置 (Hot 100)
搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0, right = n - 1, ans = n;
while(left <= right){
int mid = ((right - left) >> 1) + left;
if(nums[mid] > target){
right = mid - 1;
}else if (nums[mid] < target){
left = mid + 1;
}else{
return mid;
}
}
// left此时 > right
// left指向的是第一个大于target的元素的索引
return left;
}
};
x 的平方根
x 的平方根
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long long) mid * mid < x) {
l = mid + 1;
} else if ((long long) mid * mid > x) {
r = mid - 1;
}else{
return mid;
}
}
,
// l此时 > r,向下取整
return r;
}
};
搜索二维矩阵(Hot 100)
搜索二维矩阵
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
int left = 0, right = m * n - 1;
while(left <= right){
int mid = (right - left >> 2) + left;
int x = matrix[mid / n][mid % n];
if(x < target){
left = mid + 1;
}
else if(x > target){
right = mid - 1;
}
else{
return true;
}
}
return false;
}
};
在排序数组中查找元素的第一个和最后一个位置 (Hot 100)
在排序数组中查找元素的第一个和最后一个位置
#include <vector>
using namespace std;
class Solution {
public:
int binarySearch(vector<int>& nums, int target) {
// 二分查找变形
int left = 0, right = nums.size() - 1, ans = -1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
ans = mid;
right = mid - 1; // 找到目标值时,继续在左半部分查找
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return ans;
}
vector<int> searchRange(vector<int>& nums, int target) {
// 调用binarySearch函数,查找目标值的第一个位置
int first_pos = binarySearch(nums, target);
if (first_pos == -1) return vector<int>{-1, -1};
// 查找目标值的最后一个位置
int last_pos = first_pos;
while (last_pos < nums.size() && nums[last_pos] == target) last_pos++;
last_pos--;
return vector<int>{first_pos, last_pos};
}
};
搜索旋转排序数组 (Hot 100)
搜索旋转排序数组
//定理一:只有在顺序区间内才可以通过区间两端的数值判断target是否在其中。
//定理二:判断顺序区间还是乱序区间,只需要对比 left 和 right 是否是顺序对即可,left <= right,顺序区间,否则乱序区间。
//定理三:每次二分都会至少存在一个顺序区间。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) return mid;
if (nums[left] <= nums[mid]) { // left 到 mid 是顺序区间
(target >= nums[left] && target < nums[mid]) ? right = mid - 1 : left = mid + 1;
// 如果target在顺序区间,修改区间右边界; 如果不在,修改搜索左边界
}
else { // mid 到 right 是顺序区间
(target > nums[mid] && target <= nums[right]) ? left = mid + 1 : right = mid - 1;
// 如果target在顺序区间,修改区间左边界; 如果不在,修改搜索右边界
}
}
return -1;
}
};
寻找旋转排序数组中的最小值 (Hot 100)
寻找旋转排序数组中的最小值
class Solution {
public:
int findMin(vector<int>& nums) {
int low = 0;
int high = nums.size() - 1;
while (low < high) {
int pivot = low + (high - low) / 2;
// 如果pivot位置的值小于high位置的值,说明最小值在pivot和low之间(包括pivot)
if (nums[pivot] <= nums[high]) high = pivot;
// 否则,最小值在pivot和high之间(不包括pivot)
else low = pivot + 1; // (nums[pivot] > nums[high])
}
// 当low和high相等时,说明已经找到了最小值,返回该值
return nums[high];
}
};
if (nums[pivot] < nums[high])
else: