[LeetCode#154]Find Minimum in Rotated Sorted Array II
2015-01-18 04:21
447 查看
The question:
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.,
Find the minimum element.
The array may contain duplicates.
My first ugly solution:
An improved analysis and solution.
The improved solution:
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 7might become
4 5 6 7 0 1 2).
Find the minimum element.
The array may contain duplicates.
My first ugly solution:
public class Solution { public int findMin(int[] num) { if (num == null || num.length == 0) return -1; int low = 0; int high = num.length - 1; int mid = -1; while (low < high) { mid = (low + high) / 2; if (num[low] == num[mid] && low != mid) { low ++; continue; } if (num[low] <= num[mid] && num[low] >= num[high]) low = mid + 1; else high = mid; } return num[low]; } }
An improved analysis and solution.
This problem involves a very imporant skills in binary searching. It's very very tricky!!! The idea behind this problem is not complex. It could be classified into following three cases: 1.A[mid] > A[low], we could discard this part, and search in the range[mid+1, high] 2.A[mid] < A[low], the mininum must be included in the first part range[low, mid]. Note the mid might be the answer, thus we could not discard it. 3.A[mid] == A[low]. In this case we could not distinguish which part may hold the anwser, but we need to proceed on. One solution is to move low pointer one step forward. We could discard A[low]. The resulting answer is: public int findMin(int[] num) { if (num == null || num.length == 0) return -1; int low = 0; int high = num.length - 1; int mid = -1; while (low < high) { mid = (low + high) / 2; if (num[low] > num[mid]) high = mid; else if (num[low] < num[mid]) low = mid + 1; else low ++; } return num[low]; } However this solution has a very big pitfall!!! Because the "divide operation" only return the interger part "mid = (low + high) / 2;", Before exiting from the loop, the low pointer could point to the same element with mid pointer. Consider following two cases: 1. 3 1 low : num[0] = 3, mid: num[0] = 3. result in low++; return answer num[1] = 1. (The right answer) 2. 1 3 low : num[0] = 3, mid: num[0] = 3. result in low++; return answer num[1] = 3. (The wrong answer) What a big problem!!! An very elegant way to solve this problem. Using the same idea, we compare num[mid] and num[high], then update the solution into: while (low < high) { mid = (low + high) / 2; if (num[mid] > num[high]) low = mid + 1; else if (num[low] < num[mid]) high = mid; else high--; } return[low]; //note we reuturn[low] at here!!! If this fix works? 1. 3 1 high : num[0] = 1, mid: num[0] = 3. result in high--; return answer num[0] = 1. (The right answer) 2. 1 3 high : num[1] = 3, mid: num[0] = 1. result in high = mid = 0; return answer num[0] = 1. (The right answer) The reason is that: the high pointer would not point to the same element with mid. The invariant holds to the end!!! iff high == mid, high must equal to low, since while (low < high), this case is impossible. Note: The idea behind this method is that, this method could properly tackle the case when there are only two elements left. When only two elements left, the low pointer and mid pointer point to the same element. By comparing with the mid pointer, we could guarantee to reach the right answer by returing num[low]. if (num[mid] > num[high]) low = mid + 1; else if (num[low] < num[mid]) high = mid; else high--; When num[mid](low) > num[high], we move the low pointer to high. (low++), A[low] is the smaller. When num[mid](low) < num[high], we keep low in the same position, A[low] is the smaller.
The improved solution:
public class Solution { public int findMin(int[] num) { if (num == null || num.length == 0) return -1; int low = 0; int high = num.length - 1; int mid = -1; while (low < high) { mid = (low + high) / 2; if (num[mid] > num[high]) low = mid + 1; else if (num[low] < num[mid]) high = mid; else high--; } return num[low]; } }
相关文章推荐
- Leetcode 154: Find Minimum in Rotated Sorted Array II
- Leetcode[154]-Find Minimum in Rotated Sorted Array II
- leetcode_154 Find Minimum in Rotated Sorted Array II
- [LeetCode154]Find Minimum in Rotated Sorted Array II
- [LeetCode]题解(python):154-Find Minimum in Rotated Sorted Array II
- LeetCode(154) Find Minimum in Rotated Sorted Array II
- 【leetcode】Array——Find Minimum in Rotated Sorted Array II(154)
- LeetCode 154 Find Minimum in Rotated Sorted Array II
- 154 Find Minimum in Rotated Sorted Array II [Leetcode]
- LeetCode 154 Find Minimum in Rotated Sorted Array II
- [Leetcode 154, Hard] Find Minimum in Rotated Sorted Array II
- leetcode(153 154) FindMinimuminRotatedSortedArray与FindMinimuminRotatedSortedArray II
- !leetcode[153 & 154]:Find Minimum in Rotated Sorted Array I & II
- 【LeetCode-154】Find Minimum in Rotated Sorted Array II
- [leetcode 154] Find Minimum in Rotated Sorted Array II
- [LeetCode]154 Find Minimum in Rotated Sorted Array II
- Java for LeetCode 154 Find Minimum in Rotated Sorted Array II
- [LeetCode 154] Find Minimum in Rotated Sorted Array II
- leetcode 154: Find Minimum in Rotated Sorted Array II
- 【LeetCode-面试算法经典-Java实现】【154-Find Minimum in Rotated Sorted Array II(找旋转数组中的最小数字II)】