核心思想:一般查找有序序列中的某个元素可以采用二分查找
基本公式:mid=1+(R-L)/2
求开方
69. Sqrt(x) (Easy)
题目描述
给定一个非负整数,求它的开方,向下取整。
输入输出样例
输入一个整数,输出一个整数。
Input: 8
Output: 2
8 的开方结果是 2:82842:::,向下取整即是 2。
核心思想:while结束的条件为L>R,初始L为0,R为a,mid为1+(R-L)/2 ,sqrt为a/mid;若sqrt大于mid,则将L赋值为mid+1,若sqrt小于mid,则将R赋值为mid+1,直到mid等于sqrt
int mySqrt(int a) {
if (a == 0) return a;
int l = 1, r = a, mid, sqrt;
while (l <= r) {
mid = l + (r - l) / 2;
sqrt = a / mid;
if (sqrt == mid) {
return mid;
} else if (mid > sqrt) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return r;
}
查找区间
34. Find First and Last Position of Element in Sorted Array (Medium)
题目描述
给定一个增序的整数数组和一个值,查找该值第一次和最后一次出现的位置。
输入输出样例
输入是一个数组和一个值,输出为该值第一次出现的位置和最后一次出现的位置(从 0 开
始);如果不存在该值,则两个返回值都设为-1。
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
数字 8 在第 3 位第一次出现,在第 4 位最后一次出现。
核心思路 :还是每次减半,只不过需要分别找左边界和右边界,当nums[mid] = target时,right = mid,这样while结束时,left和right就会重合在左边界
#include <iostream>
#include <vector>
#include<algorithm>
#include <numeric>
#include <unordered_set>
#include<unordered_map>
#include <map>
#include <string>
using namespace std;
//
//
//
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target)
{
if (nums.empty())
{
return { -1,-1 };
}
int left = 0, right = nums.size(), mid,f_left=-1,f_right=-1;
//找左边界
while (left<right)
{
mid = (right + left) / 2;
if (nums[mid] >= target)
{
right = mid;
}
if (nums[mid] < target)
{
left = mid+1 ;
}
}
f_left = left;
left = 0;
right = nums.size();
//找右边界
while (left < right)
{
mid = (right + left) / 2;
if (nums[mid] > target)
{
right = mid;
}
if (nums[mid] <= target)
{
left = mid+1 ;
}
}
f_right = right-1;
if (f_left==nums.size() || nums[f_left] != target)
{
return { -1,-1 };
}
return { f_left,f_right };
}
};
旋转数组查找数字
81. Search in Rotated Sorted Array II (Medium)
题目描述
一个原本增序的数组被首尾相连后按某个位置断开(如 [1,2,2,3,4,5] ! [2,3,4,5,1,2],在第一
位和第二位断开),我们称其为旋转数组。给定一个值,判断这个值是否存在于这个为旋转数组
中。
输入输出样例
输入是一个数组和一个值,输出是一个布尔值,表示数组中是否存在该值。
Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true
核心思想:还是减半的思想,但是要先找到有序区间
#include <iostream>
#include <vector>
#include<algorithm>
#include <numeric>
#include <unordered_set>
#include<unordered_map>
#include <map>
#include <string>
using namespace std;
//start>mid 后半部分有序
//start<mid 前半部分有序
//start=mid 重复数字 start++ 跳过所有重复数字
//if 在有序区间 直接二分查找
//else if 重复上述 直到收敛到有序区间
class Solution {
public:
bool search(vector<int>& nums, int target)
{
int start = 0, end = nums.size() - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (nums[mid] == target) {
return true;
}
if (nums[start] == nums[mid]) {
// 无法判断哪个区间是增序的
++start;
}
else if (nums[mid] <= nums[end]) {
// 右区间是增序的
if (target > nums[mid] && target <= nums[end]) {
start = mid + 1;
}
else {
end = mid - 1;
}
}
else {
// 左区间是增序的
if (target >= nums[start] && target < nums[mid]) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
}
return false;
}
};
int main()
{
vector<int> nums{ 2,5,6,0,0,1,2 };
Solution s;
bool flag=s.search(nums,0);
if (flag)
{
cout << "true" << endl;
}
else
{
cout << "flase" << endl;
}
return 0;
}