力扣:二分查找
int binarySearch(vector<int>& nums, int target)
{
if(nums.size() == 0)
return -1;
int left = 0, right = nums.size() - 1;
while(left <= right)
{
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid - 1; }
}
// End Condition: left > right
return -1;
}
class Solution {
public:
int mySqrt(int x) {
if(x<2) return x;
int left=1, right=x;
while(left<=right)
{
int mid=left+((right-left)/2);
if(mid==x/mid)
{
return mid;
}
else if(mid<x/mid)
{
left=mid+1;
}
else
{
right=mid-1;
}
}
return right;
}
};
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is higher than the picked number
* 1 if num is lower than the picked number
* otherwise return 0
* int guess(int num);
*/
class Solution {
public:
int guessNumber(int n) {
int left=0,right=n;
int mid,flag;
while(left<=right)
{
mid=left+(right-left)/2;
flag=guess(mid);
if(flag==1)
{
left=mid+1;
}
else if(flag==-1)
{
right=mid-1;
}
else
{
return mid;
}
}
return -1;
}
};
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;
else if(nums[left]<=nums[mid])
{
//如果中间位置的元素大于或等于左边界的元素,说明左半部分是有序的。
//此时,再判断目标元素是否处于左半部分的有序区间内。
if(target<nums[mid]&&target>=nums[left])
right=mid-1;
else
left=mid+1;
}
else
{
//如果中间位置的元素小于左边界的元素,说明右半部分是有序的。
//此时,再判断目标元素是否处于右半部分的有序区间内。
if(target<=nums[right]&&target>nums[mid])
left=mid+1;
else
right=mid-1;
}
}
return -1;
}
};
int binarySearch(vector<int>& nums, int target){
if(nums.size() == 0)
return -1;
int left = 0, right = nums.size();
while(left < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid; }
}
// Post-processing:
// End Condition: left == right
if(left != nums.size() && nums[left] == target) return left;
return -1;
}
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
int left=1;
int right=n;
while(left<right)
{
int mid=left+(right-left)/2;
if(isBadVersion(mid))
{
right=mid;
}
else
{
left=mid+1;
}
}
return left;
}
};
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int left=0;
int right=nums.size()-1;
while(left<right)
{
//上坡有峰值
int mid=left+(right-left)/2;
if(nums[mid]>nums[mid+1])
{
right=mid;
}
else
{
left=mid+1;
}
}
return left;
}
};
int binarySearch(vector<int>& nums, int target){
if (nums.size() == 0)
return -1;
int left = 0, right = nums.size() - 1;
while (left + 1 < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid;
} else {
right = mid;
}
}
// Post-processing:
// End Condition: left + 1 == right
if(nums[left] == target) return left;
if(nums[right] == target) return right;
return -1;
}
关于这所谓的三个模板,其实就分别对应三种区间的写法:
//作者:Jungle8884
//链接:https://leetcode.cn/leetbook/read/binary-search/xe22ch/?discussion=hqOQPt
//来源:力扣(LeetCode)
// 二分查找 --- [left, right]
// 数组已经是有序的了!
public static int binarySerach1(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int left = 0, right = nums.length-1;
while (left <= right) {
// 防止溢出 等同于(left + right)/2
int mid = left + (right-left)/2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
// target 在左区间,所以[left, middle - 1]
right = mid-1;
} else {
// target 在右区间,所以[middle + 1, right]
left = mid+1;
}
}
return -1;
}
// 二分查找 --- [left, right)
// 数组已经是有序的了!
int binarySearch2(int[] nums, int target){
if(nums == null || nums.length == 0)
return -1;
// 定义target在左闭右开的区间里,即:[left, right)
int left = 0, right = nums.length;
// 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
while(left < right){
int mid = left + (right - left) / 2;
if(nums[mid] == target){
return mid;
}
else if(nums[mid] < target) {
// target 在右区间,在[middle + 1, right)中
left = mid + 1;
}
else {
// target 在左区间,在[left, middle)中
right = mid;
}
}
// Post-processing:
// End Condition: left == right
if(left != nums.length && nums[left] == target) return left;
return -1;
}
// 二分查找 --- (left, right)
// 数组已经是有序的了!
int binarySearch3(int[] nums, int target) {
if (nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length - 1;
while (left + 1 < right){
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
// target 在右区间,在(middle, right)中
left = mid;
} else {
// target 在左区间,在(left, middle)中
right = mid;
}
}
// Post-processing:
// End Condition: left + 1 == right
if(nums[left] == target) return left;
if(nums[right] == target) return right;
return -1;
}
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size()==1)
{//如果数组只有1个元素
if(nums[0]==target) return vector<int>{0,0}; //判断该元素是否等于目标值
else return vector<int>{-1,-1};
}
//用两次二分,这里用的是模板II
vector<int> res={-1,-1}; //存储结果,初始化为{-1,-1}
int left=0;
int right=nums.size()-1;
while(left<=right)
{//第一次二分查找,寻找左目标值
int mid=left+(right-left)/2;
if(nums[mid]==target)
{
res[0]=mid;
right=mid-1;
}
else if(nums[mid]>target)
{
right=mid-1;
}
else
{
left=mid+1;
}
}
left=0;
right=nums.size()-1;
while(left<=right)
{//第二次二分查找,寻找右目标值
int mid=left+(right-left)/2;
if(nums[mid]==target)
{
res[1]=mid;
left=mid+1;
}
else if(nums[mid]>target)
{
right=mid-1;
}
else
{
left=mid+1;
}
}
return res;
}
};
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
vector<int> res;
int left=0;
int right=arr.size()-1;
for(int i=0;i<arr.size()-k;i++)
{
//如果左指针所指元素与x的差值小于等于右指针所指元素与x的差值,则将右指针向左移动一位
if(abs(x-arr[left])<=abs(arr[right]-x)) right--;
else left++; //否则将左指针向右移动一位
}
for(int i=left;i<=right;i++) //将左指针到右指针之间的元素加入结果数组
res.push_back(arr[i]);
return res;
}
};