【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 ];
    }
};
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/wikiwen/p/10225941.html