题干:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
这题是上一题: https://leetcode.com/problems/search-in-rotated-sorted-array/ 的进阶版,所以看本文时最好先看过我上一篇帖子
去掉了不重复的条件限制,不要小看这个条件约束,因为当有重复时,会发生如下变化:
1,我们找pivot的方法要变,将不能再用二分法,举个极端的例子,有整个input全是1,中间突然变异出一个2,你能通过二分法确定这个2是在左半边还是右半边吗?当然不能,那么能应对这种case的方法就是线性遍历,时间复杂度瞬间变O(n)
2,在确定pivot后,你能确定要搜索的target是出现在左侧还是右侧吗?同样不能,有可能两边都会出现,所以要两侧都搜。
好在这个本身不影响时间复杂度,并且二分搜索法在两段内都能用。
基于以上思想,把之前那题的代码稍微改改,就可以work了:
package com.example.demo.leetcode;
public class SearchinRotatedSortedArrayII {
private int findPivotIndex(int[] nums, int startIndex, int endIndex){
for(int i=startIndex;i<=endIndex;i++){
if(i>0 && nums[i]<nums[i-1]){
return i;
}
}
return -1;
}
private int binarySearch(int[] nums, int startIndex, int endIndex, int target){
if(startIndex>endIndex){
return -1;
}
if(startIndex==endIndex){
return nums[startIndex]==target?startIndex:-1;
}
int midIndex = (startIndex+endIndex)/2;
if(target==nums[midIndex]){
return midIndex;
}else if(target>nums[midIndex]){
return binarySearch(nums, midIndex+1, endIndex, target);
}else{
return binarySearch(nums, startIndex, midIndex-1, target);
}
}
public int indexSearch(int[] nums, int target) {
if(nums.length<1){
return -1;
}
int pivot = findPivotIndex(nums, 0, nums.length-1);
System.out.println("pivot is: "+ pivot);
if(pivot==-1){
// already in order
return binarySearch(nums, 0, nums.length-1, target);
}
int indexInLeft = binarySearch(nums, pivot, nums.length-1, target);
int indexInRight = binarySearch(nums, 0, pivot-1, target);
if(indexInLeft!=-1){
return indexInLeft;
}
if(indexInRight!=-1){
return indexInRight;
}
return -1;
}
public boolean search(int[] nums, int target) {
int index = indexSearch(nums, target);
System.out.println("one target index: "+ index);
if(index==-1){
return false;
}else{
return true;
}
}
public static void main(String[] args) {
SearchinRotatedSortedArrayII demo = new SearchinRotatedSortedArrayII();
int[] nums = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int target = 2;
boolean ret = demo.search(nums, target);
System.out.println(ret);
}
}
反思:对数组的敏感度不够,一开始并没有想到说pivot的寻找时间复杂度会从O(log(n))变成O(n)