旋转数组问题总结

1.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.

分析:考虑该数组中的元素不重复,且数组为上升数组的旋转数组。

首先,考虑边界问题:

1.数组大小为0或者1的特殊情况;

2.使用二分法,判断nums[mid]与nums[left] 和 nums[right] 的关系。

在while(left < right) 循环中,

首先判断是否(right-left==1),如果有(right-left==1),则返回二者中的最小值;

否则判断:

1)nums[mid] > nums[left] && nums[mid] > nums[right],如,3,4,5,1,2

说明mid 处于旋转数组的前半部分,极小值位于mid后面,因此,left = mid;

2)nums[mid] > nums[left] && nums[mid] < nums[right],如,1,2,3,4,5

说明整个数组都为上升数组,极小值位于mid前面,或者就为mid本身,因此,right = mid;

3)nums[mid] < nums[left], 如,4,5,1,2,3

说明mid 处于旋转数组的后半部分,极小值位于mid前面,或者就为mid本身,因此,right = mid.

由于这里说明了数组中的元素不为0,因此,省去了对nums[mid] == nums[left] 或者 nums[mid] == nums[right] 的判断。

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

 

2.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.

分析:第2题与第1题的区别是,数组中的元素有可能是重复的。

首先,考虑边界问题:

1.数组大小为0或者1的特殊情况;

2.使用二分法,判断nums[mid]与nums[left] 和 nums[right] 的关系。

在while(left < right) 循环中,

首先判断是否(right-left==1),如果有(right-left==1),则返回二者中的最小值;

否则判断:

0) 考虑特殊情况,nums[mid] == nums[left] && nums[mid] == nums[right], 如,1,0,1,1,1;1,1,0,1,

这个时候,应对nums[left...right]进行遍历。

1)nums[mid] >= nums[left] && nums[mid] > nums[right],如,3,4,5,1,2

说明mid 处于旋转数组的前半部分,极小值位于mid后面,因此,left = mid;

2)nums[mid] >= nums[left] && nums[mid]  <= nums[right],如,1,2,3,4,5;1,3,3

说明整个数组都为上升数组,极小值位于mid前面,或者就为mid本身,因此,right = mid;

3)nums[mid] < nums[left], 如,4,5,1,2,3

说明mid 处于旋转数组的后半部分,极小值位于mid前面,或者就为mid本身,因此,right = mid.

由于这里说明了数组中的元素不为0,因此,省去了对nums[mid] == nums[left] 或者 nums[mid] == nums[right] 的判断。

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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值