旋转数组的最小数字

1.题目

假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。c++

请找出其中最小的元素。数组

示例 1:网络

输入:nums = [3,4,5,1,2]
输出:1
示例 2:ui

输入:nums = [4,5,6,7,0,1,2]
输出:0
示例 3:指针

输入:nums = [1]
输出:1code

来源:力扣(LeetCode)
连接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array
著做权归领扣网络全部。商业转载请联系官方受权,非商业转载请注明出处。排序

2.时间复杂度O(n)的解法

2.1 思路

本思路是归纳了题目和修改后的题目,暴力破解都是这个方法。ip

原数组是非递减的,旋转后,有两种状况,数组还是非递减的,例如将所有元素放到数组的末尾,它至关于仍是原数组,或者有重复项,例如 {2,2,2,2},旋转后还是非递减的,那么咱们返回第一个元素便可。另外一种状况就会出现前一个元素大于后一个元素,那么后一个元素必定是最小的,也就是咱们要的解。leetcode

2.2 代码

int findMin(vector<int>& nums) {
	if(!nums.size()) return -1;
	for(int i = 0; i < nums.size() - 1; i++) {
		if(nums[i] > nums[i + 1])
			return nums[i + 1];
	}
	return nums[0];
}

3.时间复杂度O(logn)的解法

3.1 思路

此思路是假设没有重复的数。get

咱们知道,当数组是已经排序好的,咱们能够用二分法来查找,其实本题也能够利用二分法来作。

咱们找一个中间值,若是这个中间值小于此时的left,那么就意味着咱们要找的数就在left 到 mid 中间,若是中间值大于left,那么咱们要找的值就在mid到right中间,直到缩减到两个数的时候,此时左指针指向的数必定大于右指针指向的数,mid此时就会在左指针的位置上,咱们返回右指针便可

3.2 代码

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        int mid = (left + right) / 2;
        if (nums[left] < nums[right])
        {
            return nums[left];
        }
        while (left != mid)
        {
            if (nums[mid] > nums[left])
            {
                left = mid;
            }
            else if (nums[mid] < nums[right])
            {
                right = mid;
            }
            mid = (left + right) / 2;
        }
        return nums[right];
    }
};

4.修改后的题(容许元素重复)

4.1题目

把一个数组最开始的若干个元素搬到数组的末尾,咱们称之为数组的旋转。

输入一个升序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

数组可能包含重复项。

注意:数组内所含元素非负,若数组大小为0,请返回-1。

样例

输入:nums=[2,2,2,0,1]

输出:0

题目地址

4.2解法

题目中容许出现重复的数字,这就意味着在原来的理解上咱们要多一层可能,那就是中间的值等于左侧值或者右侧的值,举一个例子[2,2,2,1,1,2],此时mid指向第三个2,最小值在mid的右侧;[2,2,2,1,1,2,2,2,2,2,2],此时最小值在mid左侧。这样咱们就须要来判断此时咱们是要在左侧寻找仍是在右侧寻找了。但无论怎么样,若是相同,咱们能够省略掉相同的数的那个指针。

因此分三种状况,当中间的比最右端的小,此时咱们让右指针移动过来,当中间的比右边打,咱们让左指针移到中间指针的后方,若是相等,就让右指针移动。

4.3代码

class Solution {
public:
    int findMin(vector<int>& nums) {
        int low = 0;
        int high = nums.size() - 1;
        while (low < high) {
            int pivot = low + (high - low) / 2;
            if (nums[pivot] < nums[high]) {
                high = pivot;
            }
            else if (nums[pivot] > nums[high]) {
                low = pivot + 1;
            }
            else {
                high -= 1;
            }
        }
        return nums[low];
    }
};

详细内容能够看这里,讲的真的很好。

相关文章
相关标签/搜索