LeetCode算法学习之--数组--寻找旋转排序数组中的最小值

510 阅读3分钟

大家好今天给大家分享下一道 LeetCode 中等难度 的题目[寻找旋转排序数组中的最小值](leetcode-cn.com/problems/co…)

这里主要是分享思路和注释,供大家更好的理解题目解法,代码部分是参考LeetCode 转写成javascript 代码,

题目

已知一个长度为 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 ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:

输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
 

分析

1.升序排序后的旋转数组,想到了二分查找

2.只有数组选择后,那么最小值一定在不是升序数组的那一方,

除非数组从左到右都是升序数列

3.因为元素不重复 所以不需要去重

这里方法有2种(自己命名 比较丑陋见谅)

1.二分查找,升序法

2.二分查找,对照第一个元素法

解法一 :二分查找,升序法(利用数组升序的特征寻找最小值)

思路
1.数组从左到右为升序则直接终止返回第一个元素nums[l]
2.如果nums[l]===nums[r]因为没有重复元素,则说明只有数组只有一个元素,也返回Nums[l]
3.如果数组nums[l]>nums[r]说明数组中存在无序数组,则利用二分法查找

*/
var findMin = function (nums) {
  let l = 0;
  let r = nums.length - 1;

  while (l <= r) {
    // 如果是升序 或者是Nums[l]等于nums[r],则直接返回nums[l]
    if (nums[l] <= nums[r]) {
      return nums[l];
    }

    // 如果数组中存在无序数组则,则通过二分查找缩小范围
    const mid = Math.floor(l + (r - l) / 2);
    if (nums[l] > nums[mid]) {
      // 注意因为最小索引存在在无序数组中,所以这里不能是r=mid-1 否则会错过答案
      r = mid;
    } else {
      // 如果是有序数组 则 直接l=mid+1 缩小范围
      l = mid + 1;
    }
  }

};

/* 复杂度
时间 O(logn)
空间 O(1)
*/

(图片来自leetcode) 方法1.png

解法二: 二分查找,对照第一个元素法

思路
1.如果是有序或者是相对这直接返回nums[l]
2.如果数组中存在无序数组则最小元素的左边一定是大于第一个元素,
右边一定是小于第一个元素
*/

var findMin = function (nums) {
  let l = 0;
  let r = nums.length - 1;

  if (nums[l] <= nums[r]) {
    return nums[l];
  }

  /* 这里不能加=,因为当l=r的时候说明数组只有一个元素,如果这个元素比nums[0]小,
  就会变成无线循环 */
  while (l < r) {
    // 如果从左到右都是升序 则直接返回l
    
    const mid = Math.floor(l + (r - l) / 2);

    if (nums[0] > nums[mid]) {
      // 这里和上题一样只能是r=mid 不然会错过答案
      r = mid;
    } else {
      // 缩小区间到右边
      l = mid + 1;
    }
  }

  return nums[l];
};

/* 复杂度
时间 O(logn)
空间 O(1)
*/

(图片截取leetCode) 方法二.png

总结

这道题 ,考察的还是大家对二分查找,和旋转数组的理解,大家多多练习多多理解,就能掌握要领。

大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢

文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com