https://oj.leetcode.com/problems/find-minimum-in-rotated-sorted-array/
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
Find the minimum element.
You may assume no duplicate exists in the array.
public int findMin(int[] num)
排序数组找数字的题目那肯定就是binary search啦。只是这一题稍微有点不一样。就是rotated过了。但基于这一题放宽了条件,no duplicate exists in the array,那么这一题就依旧可以保持logn的复杂度。
这个rotated array有一个特性是这样的。你把它从中间分成左右两半,其中一半会是一个sorted array,另一半依旧是一个rotated sorted array。
于是乎,我们可以这么和binary search采取类似的方针做。首先取中值,然后做min的判断,min的判断不难,比左右两边相邻的元素都小就是了。
否则接下来就需要判断中值左右两边哪边是sorted array,如果min不在中间,肯定也不会在sorted array的那一边。原因是因为rotated那边必然包含了min和max两个值才会形成一个rotated的样子。那么我们就继续操作rotated array那边即可。根据这一个算法,给出代码如下:
public int findMin(int[] num) {
int mid = 0, head = 0, end = num.length - 1;
while(head <= end){
mid = (head + end) / 2;
if(num[mid] < num[(mid + num.length - 1) % num.length])
return num[mid];
else if(num[mid] < num[end]){
end = mid - 1;
}else
head = mid + 1;
}
return num[head % num.length];
}事实上这题要是变化一下,变成找一个target的,其实想法也差不多,只是首先在第一步分左右的时候,判断target是否在sorted 那一边的范围之内,在的话就处理那一边,否则直接取rotated的那一边。
下面更新一个解,大致相同,只是条件判断更加简练,先上代码再解释:
public int findMin(int[] num) {
int mid = 0, head = 0, end = num.length - 1;
while(head < end){
mid = (head + end) / 2;
if(num[mid] < num[end]){
end = mid;
}else
head = mid + 1;
}
return num[head % num.length];
}这里我把判断是否同时小于前后两个元素的基本判断给去掉了,while循环的条件也从head <= end变成了head < end。另外当判断出右边是sorted array的时候,我的执行也从end = mid - 1变成了end = mid。这里解释一下:
1.当mid...end是一个sorted array的时候,我们是不能排除mid位置的元素不是我们要找的,但是mid之后的肯定不是。
2.当mid...end是一个rotated数组的时候,我们是可以排除mid位置的元素的,理由其实很简单,你可以这么去想,num[mid]最低限度是要比num[end]大的,肯定就不是min了。但是左边是sorted array,肯定也不在其中,所以就可以完全排除掉了。(如果左边是sorted array并且最小值在左边,唯一的可能就是这并不是一个rotated数组,但实际上num[mid] > num[end]这个条件已经让我们明白这是一个rotated数组,所以最小值肯定不在左边了。)
当我们排除到最后,剩下来head指向的数字肯定就是我们要找的了。
本文介绍了一种在已知无重复元素的旋转排序数组中寻找最小元素的有效算法。通过二分查找法,并利用旋转数组的特性,能够在O(log n)的时间复杂度内找到最小值。
1170

被折叠的 条评论
为什么被折叠?



