Leetcode 旋转数组的最小数字
题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof
题解
- 复杂度分析
时间复杂度上限 O(n) ,整个数组对比一遍
时间复杂度下限 O(logn),因为数组是有序的,可以使用二分查找
- 定位问题
数组的查找问题
- 算法思维
变形二分查找,一是旋转,二是有相同的元素
- 代码实现
第一种暴力解法,时间复杂度 O(n)
public static int minArray(int[] numbers) {
int res = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (res > numbers[i]) {
res = numbers[i];
}
}
return res;
}
运行时间 1ms
消耗内存 39.3 MB
第二种二分查找,时间复杂度 O(logn)
分为三种情况
- numbers[mid] < numbers[high] 说明最小值在 low, mid 区间
- numbers[mid] > numbers[high] 说明最小值在 mid+1, high 区间
- numbers[mid] == numbers[high] 说明两个区间都有可能继续递归
public static int minArray(int[] numbers) {
return findMinArray(numbers,0,numbers.length - 1);
}
public static int findMinArray(int[] numbers, int low, int high) {
if (low == high) {
return numbers[low];
}
int mid = low + ((high - low) >> 1);
if (numbers[mid] < numbers[high]) { // 说明最小值在 low, mid 区间
return findMinArray(numbers, low, mid);
} else if (numbers[mid] > numbers[high]) {// 说明最小值在 mid+1, high 区间
return findMinArray(numbers, mid + 1, high);
} else {// 相等说明两个区间都有可能继续递归
int a = findMinArray(numbers, low, mid);
int b = findMinArray(numbers, mid + 1, high);
return a < b ? a : b;
}
}
运行时间 0ms
消耗内存39.8 MB