【LeetCode & 剑指offer刷题】查找与排序题7:11旋转数组的最小数字(153. Find Minimum in Rotated Sorted Array)(系列)

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

153. Find Minimum in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]).
Find the minimum element.
You may assume no duplicate exists in the array.
Example 1:
Input: [3,4,5,1,2]
Output: 1
Example 2:
Input: [4,5,6,7,0,1,2]
Output: 0

 
/*
从头到尾遍历一遍为O(n)
*/
 
/*
问题:找旋转有序(增序)数组(不含重复数)中的最小数
分析:
    旋转后,会形成两个有序左右子数组,且左子数组的数一定比右子数组的数大
    如[3,4,5,1,2]
方法:二分查找
O(logn), O(1)
*/
class Solution
{
public:
    int findMin(vector<int> &nums)
    {
        int left = 0, right = nums.size() - 1;
        if (nums[left] > nums[right]) //若有旋转
        {
            while (left < right - 1)
            {
                int mid = (left + right) / 2;
                if (nums[left] < nums[mid]) //若中间的数大,移动left指针到中间
                    left = mid;
                else                        //若中间的数小,移动right指针到中间
                    right = mid;
            }//退出时,left = right -1,left指向左子数组的末尾,right指向右子数组的开头
            return nums[right];
        }
        else //若无旋转,直接返回第一个数
            return nums[0];
    }
};
/*
其他写法
    if (nums[mid] < nums[right]) //这种写法表示,右半段是有序的
        right = mid;
    else                        
        left = mid;
*/
 
154. Find Minimum in Rotated Sorted Array II
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]).
Find the minimum element.
The array may contain duplicates.
Example 1:
Input: [1,3,5]
Output: 1
Example 2:
Input: [2,2,2,0,1]
Output: 0
Note:

 
/*
问题:找旋转有序(增序)数组(含重复数)中的最小数
分析:
    旋转后,会形成两个有序左右子数组,且左子数组的数一定比右子数组的数大(或等于)
    如[2,2,2,0,1,1,2]
方法:二分查找,遇到相同数字时,left右移一位
平均O(logn),最坏O(n)
*/
class Solution
{
public:
    int findMin(vector<int> &nums)
    {
        if(nums.empty()) return 0;
        if(nums.size() == 1) return nums[0];
       
        int res = nums[0];
        int left = 0, right = nums.size() - 1;
        if(nums[left] >= nums[right]) //若有旋转,由于有重复数字,故这里变为大于等于
        {
            while (left < right - 1)
            {
                int mid = (left + right) / 2;
                if (nums[left] < nums[mid]) //若中间的数大,移动left指针到中间
                {
                    res = min(res, nums[left]);
                    left = mid;
                }
                else if(nums[left] > nums[mid]) //若中间的数小,移动right指针到中间
                {
                    res = min(res, nums[right]);
                    right = mid;
                }
                else //若left与mid指向数字相等,将left右移一位,略过相同数字
                    left++;
            }//退出时,left = right -1,left指向左子数组的末尾或右子数组的开头
            res = min(res, nums[left]);
            res = min(res, nums[right]);
            return res;           
        }
        else //若无旋转
            return nums[0];
    }
};
 
 
 
 
 
 

 

posted @ 2019-01-05 20:11  wikiwen  阅读(149)  评论(0编辑  收藏  举报