LeetCode 新题: Find Minimum in Rotated Sorted Array II 解题报告-二分法模板解法
Find Minimum in Rotated Sorted Array II
Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
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.
The array may contain duplicates.
SOLUTION 1:
请参考前一个题目Find Minimum in Rotated Sorted Array
1. 如何找中间断开的区间(也就是说旋转过)
我们的目的是要找出存在断口的地方。所以我们可以每次求一下mid的值,把mid
跟左边比一下,如果是正常序,就丢掉左边,反之丢掉右边,不断反复直到找到断口。
分析一下:
比如4 5 6 7 0 1 2 从中间断开后,它是由一个有序跟一个无序的序列组成的。
如果left = 0, right = 6,mid = 3, 那么4, 5, 6, 7 是正序, 7, 0, 1,
2是逆序,所以我们要丢掉左边。这样反复操作,直到数列中只有2个数字,就是断开处,这题我们会得到7,0,返回后一个就可以了。
以下图示简单描述了通过三步操作逐步逼近断口处。每一次我们可以扔掉一半,速度是LogN.
2. 特别的情况:
如果发现 A.mid > A.left,表示左边是有序,丢掉左边。
如果发现 A.mid < A.left, 表示无序的状态在左边,丢掉右边
如果A.mid = A.left,说明无法判断。这时我们可以把left++,丢弃一个即可。不必担心丢掉我们的目标值。因为A.left == A.mid,即使丢掉了left,还有mid在嘛!
每次进入循环,我们都要判断A.left < A.right,原因是,前面我们丢弃一些数字时,有可能造成余下的数组是有序的,这时应直接返回A.left! 否则的话 我们可能会丢掉解。
就像以下的例子,在1 10 10中继续判断会丢弃1 10.
举例: 10 1 10 10 如果我们丢弃了最左边的10,则1 10 10 是有序的
3.对复杂度的影响:
题目中问到了,对复杂度有何影响:实际上是有的,如果全部的数字相等,我们就退化为O(N),但是平均的复杂度仍然是O(LogN),最后复杂度的大小取决于重复的数字的多少。如果重复字数少,与logN相差不大。
1 public class Solution { 2 public int findMin(int[] num) { 3 if (num == null || num.length == 0) { 4 return 0; 5 } 6 7 int len = num.length; 8 if (len == 1) { 9 return num[0]; 10 } else if (len == 2) { 11 return Math.min(num[0], num[1]); 12 } 13 14 int left = 0; 15 int right = len - 1; 16 17 while (left < right - 1) { 18 int mid = left + (right - left) / 2; 19 // In this case, the array is sorted. 20 // 这一句很重要,因为我们移除一些元素后,可能会使整个数组变得有序... 21 if (num[left] < num[right]) { 22 return num[left]; 23 } 24 25 // left side is sorted. CUT the left side. 26 if (num[mid] > num[left]) { 27 left = mid; 28 // left side is unsorted, right side is sorted. CUT the right side. 29 } else if (num[mid] < num[left]) { 30 right = mid; 31 } else { 32 left++; 33 } 34 } 35 36 return Math.min(num[left], num[right]); 37 } 38 }
2015.1.1 Redo:
1 public class Solution { 2 public int findMin(int[] num) { 3 if (num == null || num.length == 0) { 4 return 0; 5 } 6 7 int l = 0; 8 int r = num.length - 1; 9 10 while (l < r - 1) { 11 int mid = l + (r - l) / 2; 12 13 // The array is sorted. 14 if (num[l] < num[r]) { 15 return num[l]; 16 } 17 18 if (num[mid] < num[r]) { 19 r = mid; 20 // left side is sorted. discard the left side. 21 } else if (num[mid] > num[l]) { 22 l = mid; 23 } else { 24 l++; 25 } 26 } 27 28 return Math.min(num[l], num[r]); 29 } 30 }
GitHub Code:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/binarySearch/FindMin2.java
posted on 2014-10-24 19:37 Yu's Garden 阅读(1843) 评论(0) 编辑 收藏 举报