JZ: 11 旋转数组的最小数字

题目:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如,数组 [3,4,5,1,2][1,2,3,4,5] 的一个旋转,该数组的最小值为1。  

示例 1:

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

输入:[2,2,2,0,1]
输出:0

思路:
方案一:简单的知己遍历查找:时间复杂度:O(n),空间O(1)
因为题目中所提供的是一个排序的原始数组,因此我们只要循环一次,找到变小的那个元素,这个元素就是最小元素;如果如果没有,那么第一个元素就是我们要找的元素了;
从给这个方案中的思考中,我们知道代码中要对 未经旋转的数组进行处理,不妨设置一个测试用例为
[1,2,3,4,5];

方案二:快排思想/ 二分思想 / 切分数组:时间复杂度:O(logn), 空间O(1)
对于[3,4,5,1,2], 他是两段连续增长的数组拼接而成的
我们取 起始点、中点、 终止点三个点进行比较,3 > 5 && 5 > 2
可见第一段是递增的,而第二段显然并非递增,因此最小值在第二段中;

我们重复这个过程,5 > 1 && 1 < 2,第一段不是递增的,因此对第一段继续;
而此时这两个元素只相差1个下标因此这段中的第二个值就是我们要的最小值

据此不难实现如下代码:

while(last - first >= 1){
  if(last - first == 1)
         return numbers[last];

     int mid_index = (first + last)/2;
     // 注释一:
// if(numbers[first] == numbers[last] && numbers[first] == numbers[mid_index]){
            //     return find_byOrder(numbers);
            // }

     if(numbers[first] > numbers[mid_index]){
         last = mid_index;
     }

     else if(numbers[last] < numbers[mid_index]){
         first = mid_index;
     }
 }
 return numbers[0];	// 注释2

对于刚刚说的测试用例 [1,2,3,4,5],这并不能满足,对于原地旋转的情况我们没有判断,其实只需要在return的时候:注释二;

对于小于等于3个元素的数组呢?while中的判断条件也有问题:旋转过后的数组的特点就是 first的数值要大于last,因此修改为:numbers[first] >= numbers[last]

还有一点细节!如果最初的 first 、last、mid_index对应的数值都相等怎么办?
这将不会进行任何操作,一直循环

比如:【1,0,1,1,1,1】
这时可能有一些其他的办法,这里我直接调用方法一函数,遍历查找;

方法二:代码:

class Solution {
public:
    int find_byOrder(vector<int>& numbers){
        int index = 0;
        for(int i = 1;  i< numbers.size(); i++)
        {
            if(numbers[i] < numbers[i - 1]) {
                index = i;
            }
        }
        return numbers[index];
    }
    
    int minArray(vector<int>& numbers) {

        if(numbers.size() == 0)
            return -9999;

        int first = 0, last = numbers.size()-1;

        while(numbers[first] >= numbers[last]){
            if(last - first == 1)
                return numbers[last];

            

            int mid_index = (first + last)/2;

            if(numbers[first] == numbers[last] && numbers[first] == numbers[mid_index]){
                return find_byOrder(numbers);
            }

            if(numbers[first] > numbers[mid_index]){
                last = mid_index;
            }

            else if(numbers[last] < numbers[mid_index]){
                first = mid_index;
            }
        }
        return numbers[0];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值