无法找到一个条件形成OOXX模型
但是可以根据判断,每次只保留有解的一半,去掉无解的一半
1. Find Peak Element
你给出一个整数数组(size为n),其具有以下特点:
- 相邻位置的数字是不同的
- A[0] < A[1] 并且 A[n - 2] > A[n - 1]
假定P是峰值的位置则满足A[P] > A[P-1]
且A[P] > A[P+1]
,返回数组中任意一个峰值的位置。
注意事项
- It's guaranteed the array has at least one peak.
- The array may contain multiple peeks, find any of them.
- The array has at least 3 numbers in it.
给出数组[1, 2, 1, 3, 4, 5, 7, 6]
返回1
, 即数值 2 所在位置, 或者6
, 即数值 7 所在位置.
mid在数据中的分布可能有以下几种情况
当mid值在第一种情况,那么峰值一定在右侧,将start = mid即可
当mid值在第二种情况,那么峰值一定在左侧,将end = mid即可
当mid在第三种情况,那么就找到峰值。
当mid在第四种情况,那么峰值可能出现在左侧,也可能出现在右侧。
public class findPeak { public int findPeak(int[] A) { if (A == null || A.length == 0) { return -1; } int results = 0; int start = 1; int end = A.length - 2; while (start + 1 < end) { int mid = start + (end -start) / 2; if (A[mid - 1] < A[mid] && A[mid] > A[mid + 1]) { results = mid; break; } else if (A[mid - 1] < A[mid] && A[mid] < A[mid + 1]) { start = mid; } else if (A[mid] < A[mid - 1] && A[mid + 1] < A[mid] ) { end = mid; } } if (A[start - 1] < A[start] && A[start] > A[start + 1]) { results = start; } else { results = end; } return results; } }
if (A == null || A.length == 0) { return -1; } int start = 1; int end = A.length - 2; while (start + 1 < end) { int mid = start + (end - start) / 2; if (A[mid] < A[mid + 1]) { start = mid; } else if (A[mid] < A[mid - 1]) { end = mid; } else { start = mid; } } if (A[start] < A[end]) { return end; } else { return start; }OOOXXX形式是升序的形式。
找寻找数组中的最小值
讲数组转化为OOOXXX的形式,让找到数组中第一个或最后一个满足条件的位置,OOOXXXX 前面是升序的,后面也是升序的。
旋转排序数组包括排序数组([1,2,3,4,5])
为什么以最后一个值作为参考?因为可能包含[1,2,3,4,5]这种旋转排序数组,最小值在左侧。
以最后一个值作为参考值,找到最小值的位置,如果mid大于最后一个值,那么肯定是在右侧,否则肯定在左侧。
public int findMin(int[] nums) { if (nums == null || nums.length == 0) { return -1; } int start = 0; int end = nums.length - 1; int target = nums[end]; while (start + 1 < end) { int mid = start + (end - start) / 2; if (nums[mid] > target) { start = mid; } else { end = mid; } } return Math.min(nums[start], nums[end]); }
搜索旋转排序数组
在一个旋转数组中搜索目标值
记住在while 循环中不是为了找目标值,而是为了每次都能将目标值的范围缩小一半。
旋转的排序数组包含排序数组。(Rotated Sorted Array 包含 Sorted Array)
现在需要思考的是如何每次取到一个mid值就缩小一次范围?
mid会出现在上部或者在下部。
这样可以将mid出现在上部或者下部分别讨论。
当mid出现在上部时(A[mid] >= A[start]),target可能出现在两边, 当 start<=target<=mid ,那么end = mid
或者 target>=mid || target <=start 那么start = mid
当mid出现在下部时,target也可能在两边,当 mid<=target<=end ,那么start = mid
当target <= mid || target >=start 那么end = mid
public int search(int[] A, int target) { if(A == null || A.length == 0) { return -1; } int start = 0; int end = A.length - 1; int mid; while (start + 1 < end) { mid = start + (end - start) / 2; if (A[mid] == target) { return mid; } if (A[mid] >= A[start]) { if (target <= A[mid] && target >= A[start]) { end = mid; } else { start =mid; } } else { if (target >= A[mid] && target <= A[end]) { start = mid; } else { end = mid; } } } if (A[start] == target) { return start; } else if (A[end] == target){ return end; } else { return -1; } }