数据结构与算法--二分查找

核心思想:一般查找有序序列中的某个元素可以采用二分查找
基本公式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;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值