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

文章目录

  • 前言
  • [1. 寻找旋转排序数组中的最小值](https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/)
    • 1.1 二分
  • 2. [寻找旋转排序数组中的最小值 II](https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array-ii/)
    • 2.1 二分
  • 3. [搜索旋转数组](https://leetcode.cn/problems/search-rotate-array-lcci/)
    • 3.1 二分
  • 总结


前言

很久没有写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;
    }
};

总结

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

你可能感兴趣的:(LeetCode千题之路,leetcode,算法,c++)