无法找到一个条件形成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;
}
}