本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
已知一个长度为 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 次得到输入数组。
提示:
- n == nums.length
- 1 <= n <= 5000
- -5000 <= nums[i] <= 5000
- nums 中的所有整数 互不相同
- nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
二、思路分析:
- 遍历后查找最小值 AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
let min = nums[0];
for(let i = 1; i < nums.length; i ++) {
if(nums[i] < min) min = nums[i];
}
return min;
};
执行结果
执行结果:通过
执行用时:96 ms, 在所有 JavaScript 提交中击败了18.55%的用户
内存消耗:38.1 MB, 在所有 JavaScript 提交中击败了38.99%的用户
缺点:时间复杂度最大
- 数组重新升序排序后取第一个 AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
nums.sort((a, b) => {
return a - b;
});
return nums[0];
};
执行结果
执行结果:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了97.16%的用户
内存消耗:39.1 MB, 在所有 JavaScript 提交中击败了5.05%的用户
缺点:时间复杂度也最长
- 二分法
- 查找有序数组,尝试使用
二分法 - 使用
(end - start) / 2获得中间位置mid,使用Math.floor向下取整 - 判断中间位置值
nums[mid]和末尾位置值nums[end]是否是升序,是升序则说明最小值在中间位置的左边部分,把结束位置置为原中间位置end = mid - 若是不是升序则最小值在右边部分,把开始位置置为原中间位置加一
start = mid + 1 - 继续二分,直到起始位置不小于结束位置,返回起始位置的值
nums[start]AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
let start = 0;
let end = nums.length - 1;
while (start < end) {
const mid = start + Math.floor((end - start) / 2);
if (nums[mid] < nums[end]) {
end = mid;
} else {
start = mid + 1;
}
}
return nums[start];
};
执行结果
执行结果:通过
执行用时:84 ms, 在所有 JavaScript 提交中击败了64.33%的用户
内存消耗:37.7 MB, 在所有 JavaScript 提交中击败了94.00%的用户
三、总结:
- 数组遍历查找效率最低
- 利用数组自带排序sort可利用JavaScript内部优化,提升部分效率
- 二分查找提高查找效率