package BisectionMethod;
/**
* 二分法精髓就是每次努力扔掉一半
* 81.搜索旋转排序数组 II
* 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。
* 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,
* 使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。
* 例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
* 给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。
* 你必须尽可能减少整个操作步骤。
* */
/**
* 这题难点在于怎么判断不符合条件的一半, 如果不能扔掉一半, 起码要不断地缩小空间.
* 每次拿到一个mid后, 如果它不等于target, 那么它可以将整个区间分为左侧[left, mid) 和右侧(mid, right),
* 而且整个两个区间值总有一个是有序的, 我们只有判断target是不是在有序的区间内, 是的话就可以把另外一半扔掉, 不在这有序的区间内的话, 就扔掉有序的这一半.
*
* 每一次二分后: 如果target已经找到, 可以直接返回,
* 否则剩余区间可以分为2个部分[left, mid) 和 (mid, right);
* 情况1: nums[mid] > nums[left] : 暗示[left, mid) 有序的, (mid, right)则是螺旋的
* 判断target 是不是在[left, mid), 如果是则right = mid, 不在这个区间的话, 那么肯定在(mid, right), left = mid + 1;*
* 情况2: nums[mid] < nums[left] : 暗示(mid, right) 是有序的
* 判断target 是不是在(mid, right) 中, 如果是则left = mid +1, 不在这个区间的话, 那么肯定在[left, mid), right = mid;*
* 情况3: nums[mid] == nums[left], 无法区分,但是由于nums[mid] != target, 可以left++;
* */
public class SearchInRotatedSortedArray2 {
public static void main(String[] args) {
int [] arr = {0,1,2,4,4,4,5,6,6,7};
int target = 4;
boolean flag = search(arr,target);
System.out.println(flag);
}
public static boolean search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return true;
}
// 1.
if (nums[mid] > nums[left]) {
if (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid;
}
}
// 2.
else if (nums[mid] < nums[left]) {
if (target <= nums[right] && target > nums[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
// 3.
else {
left++;
}
}
return false;
}
}