Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?
这个是接着上一篇的:http://blog.csdn.net/lgd_yyf/article/details/40536943
针对原题中有重复数字的情况,在上一篇递归解法的基础之上,稍作修改即可。
注意到,我们在选择下一次递归的位置时,可以发现,在无重复数字时,只有两种情况:
1、num[mid] > Math.max(num[start], num[end])
2、num[mid] < Math.min(num[start], num[end])
但是包含重复数字时,情况就不一样了,有可能出现num[mid]和其中一个相等的情况,故需要分类讨论。在分类之前,对数组做如下处理:若rotate的位置恰好出现重复数字当中,则将后面的重复数字去掉(这一点在后面分类的时候,将起到作用)。下面开始分类:(函数为 public int searchMin(int[] num, int start, int end) ;)
int mid=(start+end)/2;
1、num[mid] >= num[start] && num[mid] <= num[end] 示例:[ 4,3,1,1,1] 或 [3,4,1,1,1] 或 [1,1,1,1,1]
若都取等号,则说明数组都是同一数字,无论何种递归,最后都会返回正确值;
若 num[mid] == num[start],则 num[mid] < num[end] ,根据上篇所讲的取 最小值和最大值原理,
return searchMin(num, mid, end);
同理,若 num[mid] == num[end],则
return searchMin(num, mid, end);
2、num[mid] <= num[start] && num[mid] >= num[end] 示例:[ 1,1,1,4,3] 或 [1,1,1,3,4]
若 num[mid] == num[start],则 num[mid] > num[end] ,根据上篇所讲的取 最小值和最大值原理,
return searchMin(num, mid, end);
同理,若 num[mid] == num[end],则
return searchMin(num, mid, end);
3、num[mid] >= num[start] && num[mid] >= num[end] 示例:[ 4,3,6,6,5] 或 [3,4,5,5,1]
4、num[mid] <= num[start] && num[mid] <= num[end] 示例: [ 3,4,1,1,2] 或 [4,3,1,6,5]3、4情况就是和上一题中的原理一样,这里不再赘述。
事实上,在判断的时候 用 if-else if-else对1、2、3、4顺序判断下来 ,3、4中的等号情况是不会出现的。
实现如下:
public int findMin(int[] num) {
int len = num.length;
// 去掉末尾和开头重复的部分
if (num[0] == num[len - 1]) {
while (len >= 2 && num[len - 2] == num[len - 1])
len--;
len--;
}
if (len <= 1) {
return num[0];
}
return searchMin(num, 0, len - 1);
}
public int searchMin(int[] num, int start, int end) {
if (start + 1 == end) {
return Math.min(num[start], num[end]);
}
int mid = (start + end) / 2;
if (num[mid] >= num[start] && num[mid] <= num[end]) {
if (num[mid] == num[start])
return searchMin(num, mid, end);
else
return searchMin(num, start, mid);
} else if (num[mid] <= num[start] && num[mid] >= num[end]) {
if (num[mid] == num[end])
return searchMin(num, start, mid);
else
return searchMin(num, mid, end);
} else if (num[mid] >= num[start] && num[mid] >= num[end]) {
if (num[start] > num[end])
return searchMin(num, mid, end);
else
return searchMin(num, start, mid);
} else {
if (num[start] > num[end])
return searchMin(num, start, mid);
else
return searchMin(num, mid, end);
}
}