leetcode-153寻找旋转排序数组中的最小值

leetcode刷题

153. 寻找旋转排序数组中的最小值

题目

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

分析

​ nums是一个经过旋转后的有序数组。根据二分法将矩阵分为[left:mid]和[mid:right]两部分,首先判断循环结束条件。即nums[mid]比两边的数都小nums[mid]<=nums[mid-1]和nums[mid]<=nums[mid+1],注:因为是java,所以要写成nums[mid]<=nums[(mid+nums.length-1)%nums.length] && nums[mid]<=nums[(mid+1)%nums.length],其中+length以及%length是为了防止首和尾,python就不用考虑这个问题了;而=号是为了防止只有nums.length==1

​ 接下来只对[left:mid]进行分析,判断什么情况下最小值会留在[left:mid]区域。如图一所示,当[left:mid]呈现下图趋势时nums[left]>nums[mid],最小值一定存留在本区域,不用考虑[mid:right]。

图一

图二

​ 而[left:mid]呈图二中的趋势时候,需要考虑[mid:right]区域,其具有三种可能,但是只有呈现①中的趋势时nums[right]>nums[mid] and nums[right]>nums[mid] 合并为nums[right]>nums[left],最小值才会留在[left:mid]区域中。

若留在[left:mid]中,即将right = mid - 1保留该区域,撇弃[mid:right]。反之亦然left = mid + 1

代码
public int findMin(int[] nums) {
    int left = 0;
    int right = nums.length-1;
    int mid;
    while(left<=right){
        mid = (left+right)/2;
        if (nums[mid]<=nums[(mid+nums.length-1)%nums.length] && nums[mid]<=nums[(mid+1)%nums.length]){
            return nums[mid];
        }
        else if (nums[left]>nums[mid] || nums[right]>nums[left]){
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return -1;
}
结果

时间超过100.00%

内存超过70.75%

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值