365天挑战LeetCode1000题——Day 016 旋转数组


前言

很久没有写LeetCode题了……因为最近是考试周,必须得在LeetCode和考试中做一个抉择了。
前两天考完了两科,马原和数电,接下来的都是和计算机相关性很大的,所以复习的压力不是特别大了。
今天在复习算法的时候,看到了旋转数组问题,以前写过,现在又忘了,就通过LeetCode把这一类问题都写完了罢……
首先通过刷一类题,我发现LeetCode的难度值得吐槽,为什么呢,点了这几题的超链接你就知道了……
二分法的基本模板如下:

while (l < r) {
	int m = l + r >> 1;
	if (check(m)) r = m;
	else l = m + 1;
}

通过这个模板最终你可以得到r==l,但[r]不一定是你想要的值,接下来你还要做一个判断,具体的看后面。


1. 寻找旋转排序数组中的最小值

1.1 二分

把右端点作为二段性的判断依据:

class Solution {
public:
    int findMin(vector<int>& numbers) {
        int l = 0;
	    int r = numbers.size() - 1;
	    while (l < r) {
		    int m = l + r >> 1;
		    if (numbers[m] <= numbers.back()) r = m;
		    else l = m + 1;
	    }
	    return numbers[l];
    }
};

2. 寻找旋转排序数组中的最小值 II

2.1 二分

有可能有重复的数字,会破坏第一问的二段性,所以需要进行预处理,使得l要大于右端点:

class Solution {
public:
    int findMin(vector<int>& numbers) {
        int l = 0;
	    int r = numbers.size() - 1;
        while (l < numbers.size() - 1 && numbers[l] == numbers[r]) l++;
	    while (l < r) {
		    int m = l + r >> 1;
		    if (numbers[m] <= numbers.back()) r = m;
		    else l = m + 1;
	    }
	    return numbers[l];
    }
};

3. 搜索旋转数组

3.1 二分

根据前两问可以将这个问题转换为有序数组的搜索,注意的细节是需要返回最小的那个索引,有可能我们搜出来的结果是左端点,这时候加一句判断target是否等于左端点:

class Solution {
public:
    int search(vector<int>& numbers, int target) {
        int l = 0;
	    int r = numbers.size() - 1;
        while (l < numbers.size() - 1 && numbers[l] == numbers[r]) l++;
	    while (l < r) {
		    int m = l + r >> 1;
		    if (numbers[m] <= numbers.back()) r = m;
		    else l = m + 1;
	    }
        if (target <= numbers.back()) r = numbers.size() - 1;
        else {
            l = 0;
            r--;
        }
        while (l < r) {
            int m = l + r >> 1;
            if (numbers[m] >= target) r = m;
            else l = m + 1;
        }
        if (target != numbers[l]) return -1;
        if (target == numbers[0]) return 0;
        while (l > 0 && (numbers[l - 1] == numbers[l])) {
            l--;
        }
        return l;
    }
};

总结

通过三道题目强化学了下二分的思想……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值