剑指offer面试题11. 旋转数组的最小数字

欢迎访问我的剑指offer(第二版)题解目录
对应的Leetcode题目可点击153. Find Minimum in Rotated Sorted Array154. Find Minimum in Rotated Sorted Array II

题目描述

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. Find the minimum element.

旋转数组中没有重复元素(153. Find Minimum in Rotated Sorted Array

算法设计

可以使用二分查找算法查找最小元素。查看索引为[left,right]的子数组。我们可以发现,如果第一个成员小于最后一个成员,则数组中没有旋转。因此,我们可以直接返回此子数组中的第一个元素。
如果第一个元素大于最后一个元素,则我们计算中间的元素,并将其与第一个元素进行比较。如果中间元素的值大于第一个元素,则我们知道旋转在此数组的后半部分。否则,它位于阵列的前半部分。按照这个性质进行二分查找即可。

C++代码

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

旋转数组中有重复元素(154. Find Minimum in Rotated Sorted Array II

算法设计

依然可以采取上面的二分查找算法,只不过需要注意到一种情况,就是当中间元素与首尾元素都相等时,要采用线性查找算法。例如对于数组[1,0,1,1,1][1,1,1,0,1],当查找到中间元素1时,是无法根据它与首尾元素的大小比较进行二分的,这时需要对这一区间进行线性查找。

C++代码

class Solution {
  public:
    int findMin(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;
        while (left < right) {
            if (nums[left] < nums[right])
                return nums[left];
            int mid = left + (right - left) / 2;
            if (nums[left] == nums[right] and nums[left] == nums[mid]) {
                return *min_element(nums.begin() + left, nums.begin() + right + 1);
            } else if (nums[mid] >= nums[left]) {
                left = mid + 1;
            } else if (nums[mid] <= nums[right]) {
                right = mid;
            }
        }
        return nums[left];
    }
};
发布了528 篇原创文章 · 获赞 1015 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/richenyunqi/article/details/103960192