假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。
示例 1:
输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
示例 2:
输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false
(1)方法:暴力法
思路:直接遍历逐个比较即可;
弊端:有很多不必要的计算,浪费时间;
class Solution {
public boolean search(int[] nums, int target) {
return search1(nums, target);
}
//暴力法,逐个遍历
private boolean search1(int[] nums, int target) {
if (nums.length == 0)
return false;
for (int n : nums) {
if (n == target)
return true;
}
return false;
}
}
(2)方法:双指针法
思路:双指针,一个开头一个结尾,其实不管有序数组怎么旋转,它肯定还是由两个有序数组片段组成,头指针对应的递增片段,尾指针对应的递减片段,只需要确定当前目标值属于哪个片段,然后只遍历对应该片段即可;
1,先把特殊情况剔除掉,target完全不属于这两个片段,返回false;target刚好等于头尾指针对应的值,返回true即可;
2,target处于头指针对应的递增片段,target>nums[start],直接将start+1,只要target比nums[start]大,并且start没越界,同时还要保证此时指针仍处于该递增片段,那么start++,一直重复此操作,直到不满足条件,然后判断start指针是否越界以及是该索引的值否和target相等,相等则返回true,否则false;
3,target处于尾指针对应的递减片段,和头指针的思路一样,只是end指针向左移动而已;
注2:具体可以看代码
class Solution {
public boolean search(int[] nums, int target) {
return search2(nums, target);
}
//双指针法
private boolean search2(int[] nums, int target) {
if (nums.length == 0)
return false;
//定义双指针,起始
int start = 0, end = nums.length - 1;
//特殊情况,超出有序数组范围肯定是false
if (nums[start] > target && nums[end] < target)
return false;
//刚好等于边界值
if (nums[start] == target || nums[end] == target)
return true;
//比右边界值小时
if (nums[end] > target) {
end --;//右指针向左移动一位,然后判断是否还大于target
while (end >= 0 && nums[end] > target && nums[end] <= nums[end+1])
end--;
//此时nums[end] <= target了
if (end < 0 || nums[end] != target) //要么遍历完成,要么在当前有序片段中不存在
return false;
else
return true;
} else {//比左边界值大时
start ++;//左指针右移一位继续判断是否比target小
while (start < nums.length && nums[start] < target && nums[start] >= nums[start-1])
start ++;
if (start >= nums.length || nums[start] != target)
return false;
else
return true;
}
}
}