天天看點

81. Search in Rotated Sorted Array II31 Search in Rotated Sorted Array ll81題目

31 Search in Rotated Sorted Array ll

描述不包含相同的元素情況

Input: nums = [4,5,6,7,0,1,2], target = 0

Output: 4

對有序數組進行一定的旋轉,進行查找

二分查找and雙指針

這是二分查找的變體,

雙指針的形式,low = 0, high = length-1;

mid 中間分為兩個部分

形式

  • nums[mid]< nums[r], 這是有序的,可以在這部分進行二分查找

    - 如果nums[mid]<target<= nums[r] , 則可以抛棄左邊部分

    - 否則抛棄右部分

  • nums[mid]>nums[r], 則nums[l] 到 nums[mid] 是有序,

    - 如果nums[l]<target<=nums[mid], 則在這左部分進行二分查找

    - 否則抛棄左部分

找出其中滿足二分查找的部分

class Solution {
    public int search(int[] nums, int target) {
      if(nums==null||nums.length==0) return -1;
      int n = nums.length;
      int l=0,right = n-1;
        
        while(right>=l)
        {
            int mid = (l+right)/2;
          
            if(nums[mid]==target)
                return mid;
            //在這裡也可以換成nums[left], 比較
            if(nums[mid] < nums[right])
            {
                if(nums[mid]<target && nums[r]>=target)
                {
                    l = mid+1;
                }
                else
                    right = mid-1;
            }
            else
            {
                if(nums[l]<= target && nums[mid]>target )
                    right = mid-1;
                else 
                    l = mid+1;
            }
        }
        return -1;
    }
}
           

另一種方式寫法情況, 主要跟nums[left]與nums[mid]

public class Solution {
    public boolean search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (target == nums[mid]) return true;
            if (nums[mid] == nums[left]) left++;
            else if (nums[mid] > nums[left]) {
                if (nums[left] <= target && nums[mid] > target) right = mid - 1;
                else left = mid + 1;
            } else {
                if (nums[mid] < target && target <= nums[right]) left = mid + 1;
                else right = mid - 1;
            }
        }
        return false;
    }
}
           

複雜度

二分查找時間複雜度為olog(N), 空間複雜度為O(1)

81題目

  • 如果包含相同元素,那麼就有可能在兩邊都有都有相同的元素,
  • 你并不知道應該跳向哪一半。解決的辦法隻能是對邊緣移動一步,直到邊緣和中間不在相等或者相遇,這就導緻了會有不能切去一半的可能。
  • 是以最壞情況(比如全部都是一個元素,或者隻有一個元素不同于其他元素,而他就在最後一個)就會出現每次移動一步,總共是n步,算法的時間複雜度變成O(n)。代碼如下:

是以比較 nums[mid] 與nums[right], 如果兩個相等,則放棄一遍的,放棄右邊的

if(nums[mid]==nums[right])
    right--;
           

是以就增加了一種情況,

在31題目中

  • nums[mid]>nums[right]
  • nums[mid] < nums[right]

在81題中

  • nums[mid]<nums[right]
  • nums[mid]>nums[right]
  • nums[mid] =nums[right]
class Solution {
    public boolean search(int[] nums, int target) {
        if(nums==null||nums.length==0) {return false;}
       
        int n = nums.length;
        
        int l=0,r = n-1;
   
        while(r>=l)
        {
            int mid = (l+r)/2;
            if(nums[mid]==target)
                return true;
           
            
            if(nums[mid] < nums[r])
            {
                if(nums[mid]<target && nums[r]>=target)
                {
                    l = mid+1;
                }
                else
                { r = mid-1;}
            }
            else if(nums[mid]>nums[r])
            {
                if(nums[l]<= target && nums[mid]>target )
                {
                    r = mid-1;
                }
                else
                { 
                    l = mid+1;
                }
            }
            else {
              --r;
            }
        }
        return false;
    }
}