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.
这题事实上就是找翻转后右側部分的最左端点。典型的二分搜索变体,大致思路分成两种情况讨论:
1)假设搜索范围在翻转部分,略微复杂一点:
1.1)假设中间点在翻转后的左側,则应该往右寻找。由于假设没有冗余元素。最小值不可能出如今左側;
1.2)假设中间点在翻转后的右側。则应该往左寻找。只是这时应该缓存下当前中间点相应的元素,由于再往左的话,可能就到了翻转后的左側部分。就可能错过全局最小值了。
2)假设搜索范围在排序的部分。则当前的最小值肯定是在最左端。
只是这个时候最左端的值不一定是全局最小。须要跟缓存的最小值在进行一次比較。
public int findMin(int[] num) { int low = 0, high = num.length - 1; int ret = Integer.MAX_VALUE; while (low <= high) { int mid = low + (high - low) / 2; // On the sorted part. if (num[low] <= num[high]) { return Math.min(num[low], ret); } else { // On the rotated part. // num[mid] is on the left rotated part. if (num[mid] >= num[low]) { low = mid + 1; } else { // num[mid] is on the right rotated part. ret = num[mid]; high = mid - 1; } } } return ret; }
注意最后的return语句事实上是不可能到达的。由于一旦low和high相等,那么num[low]和num[high]也必定相等了,直接就返回了。
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.
假设存在冗余元素,那么则必须把num[low]和num[high]相等的情况单独讨论了。这样的情况下。仅仅能老老实实的线性搜索了。假设使用二分查找,这个时候可能会出问题:假设输入数组的最左和最右元素相等,并且都存在一片连续相等的区域,那么中间点可能也会在最左或者最右的连续相等区域中。这个时候应该是无法推断再往哪个方向搜索的。比如[3, 3, 3, 3, 3, 3, 4, 2, 3, 3]和[3, 3, 4, 2, 3, 3, 3, 3, 3, 3],取中间点后根本无法推断继续往哪个方向搜索。
public int findMin(int[] num) { int low = 0, high = num.length - 1; int ret = Integer.MAX_VALUE; while (low <= high) { // Linear scan to find a non-flat part. if (num[low] == num[high]) { ret = Math.min(num[low], ret); low++; continue; } int mid = low + (high - low) / 2; // On the sorted part. if (num[low] < num[high]) { return Math.min(num[low], ret); } else { // On the rotated part. // num[mid] is on the left rotated part. if (num[mid] >= num[low]) { low = mid + 1; } else { // num[mid] is on the right rotated part. ret = num[mid]; high = mid - 1; } } } return ret; }
相比于之前不考虑冗余元素的解法,就是多了一个if语句,单独处理num[low]和num[high]相等的情况。