题目描述:
单调有序数组被循环右移k 位后,找最小值,时间复杂度的要求log N 。
一个有序数组循环右移n位,找到右移后该数组的最小值,数组中可能包含重复元素。
以最小值的位置分类,可以分成两种,一种是在中间偏左,一种实在中间偏右。
上图表示最小值在中间偏左的情况,由于原数组是递增序列,所以nums[middle : right]是递增的,即nums[middle]<nums[right],此时可以确定将结果缩小到nums[left : middle]这个范围内
同理,当最小值在中间偏右时,nums[left : middle]是递增的,根据大小关系可知nums[middle]>nums[right],此时可以确定将结果缩小到nums[middle+1 : right]这个范围内
而当nums[middle]==nums[right]时,无法确定最小值的位置,此时可以做的事情是尽量缩小范围,又因为知道nums[middle]和nums[right]值相同,所以nums[right]可以抛弃,即将结果范围缩小到nums[left : right-1]重新计算(注意,目的是找最小值而不是第一个最小值的位置,所以就算nums[right]是第一个最小值也无关紧要)
show code:
public static void main(String[] args) {
int[] arr = new int[]{7, 8, 9, 1, 1, 2, 3, 4, 5, 6};// 789123456
System.out.println(findMin(arr));
}
public static int findMin(int[] nums) {
int n = nums.length;
int left = 0;
int right = n - 1;
while (left < right) {
int middle = left + (right - left) / 2;
if (nums[middle] < nums[right]) {
right = middle;
} else if (nums[middle] > nums[right]) {
left = middle + 1;
} else {
right = right - 1;
}
}
return nums[left];
}
//output
1