This is more fun to do. This is no longer a vanilla binary search. This is decrease and conquer. We need to exploit the sorted property and somehow pick half of the original problem to solve. We have 4 cases:
1. mid is peak, then A[mid-1] < A[mid] < A[mid+1]
2. if the seq is increasing, then search right
3. if the seq is decreasing, then search left
4. else mid is a trough, either left or right is fine
Code
public int findPeakElement(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
return peakHelper(nums, 0, nums.length - 1);
}
private int peakHelper(int[] nums, int start, int end) {
// base case 2 elements (make sure no array out of bound exception)
if (start + 1 >= end) {
if (nums[start] > nums[end]) {
return start;
} else {
return end;
}
}
// decrease
int mid = start + (end - start) / 2;
// conquer
if (nums[mid - 1] < nums[mid] && nums[mid] > nums[mid + 1]) {
// nums[mid] is a peak
return mid;
} else if (nums[mid - 1] < nums[mid] && nums[mid] < nums[mid + 1]) {
// in an increasing seq, search right
return peakHelper(nums, mid + 1, end);
} else if (nums[mid - 1] > nums[mid] && nums[mid] > nums[mid + 1]) {
// in a decreasing sq, search left
return peakHelper(nums, start, mid - 1);
} else {
// a trough, either left or right
return peakHelper(nums, start, mid - 1);
}
}
The comparisons can be further simplified. But since we have a clear understanding and a working code, objectives accomplished.
Maximum Number in Mountain Sequence
Given a mountain sequence of n integers which increase firstly and then decrease, find the mountain top.
Example
Given nums = [1, 2, 4, 8, 6, 3] return 8
Given nums = [10, 9, 8, 7], return 10
Analysis
Same thing as above. Let's try while loop this time.
Code
public int mountainSequence(int[] nums) {
if (nums == null || nums.length == 0)
return -1;
int start = 0, mid, end = nums.length - 1;
// guarantee more than 2 elements
while (start + 1 < end) {
mid = (start + end) / 2;
if (nums[mid - 1] < nums[mid] && nums[mid] > nums[mid + 1]) {
// a peak
return nums[mid];
} else if (nums[mid - 1] < nums[mid] && nums[mid] < nums[mid + 1]) {
// increasing seq, search right
start = mid + 1;
} else {
// decreasing seq, or a trough, search left
end = mid - 1;
}
}
// base case
if (nums[start] > nums[end]) {
return nums[start];
} else {
return nums[end];
}
}