剑指OfferDay1
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
示例1
输入
[3,4,5,1,2]
返回值
1
此题的的意思是 :
初始一个序列将任意数目的元素进行旋转到末尾,相当于两个递增的数组
例如:初始数组 1 2 3 4 5 旋转3个元素 为 4 5 1 2 3 然后找出最小的元素 1
思路:可以采用 暴力法 但是没有用到题目中递减排序的条件。
所以此处采用二分法的思想
找到中间值,和最左下标元素 i 或者最右下标元素 j 进行比较,然后逐渐缩小范围
此处缩减范围会出现以下情况(以下都是和最右下标进行比较)
- 中间值大 arr[mid] > arr[j] : 3 4 5 1 2 arr[mid] = 4 arr[j] = 2 所以此时最小元素肯定在 [mid+1 - j] 区间处,所以令 i = mid+1
- 中间值小 arr[mid] < arr[j] :5 1 2 3 4 同理 最小元素肯定在 [i - mid] 处 j = mid
- 相等 arr[mid] = arr[j] :1 1 1 0 1 根据题目不会出现此种情况,但是需要分析 此时不确定最小值在左边还是右边,则让 j–,慢慢缩小区间
代码
以右边为比较
public int minNumberInRotateArray(int [] array) {
if (array.length == 0) return 0;
int i = 0;
int j = array.length-1;
while (i < j){
if (array[i] < array[j]) return array[i]; //当array[i] < array[j]则找到最小值
int mid = (i + j) >>1;
if (array[mid] > array[j]){
i = mid+1;
}else if (array[mid] < array[j]){
j = mid;
}else {
j--;
}
}
return array[i];
}
以左边为比较
public int minNumberInRotateArray(int[] array) {
if (array.length == 0) return 0;
int i = 0, j = array.length - 1;
while (i < j) {
if (array[i] < array[j]) {
return array[i];
}
int mid = (i + j) >> 1;
if (array[mid] > array[i]) {
i = mid + 1;
} else if (array[mid] < array[j]) {
j = mid;
} else{
i++;
}
}
return array[i];
}
时间复杂度分析:
普通情况 O(log2 n)
特殊情况O(n)