leetcode 33. 搜索旋轉(zhuǎn)排序數(shù)組

題目描述

假設(shè)按照升序排序的數(shù)組在預(yù)先未知的某個(gè)點(diǎn)上進(jìn)行了旋轉(zhuǎn)。
( 例如,數(shù)組 [0,1,2,4,5,6,7] 可能變?yōu)?[4,5,6,7,0,1,2] )。
搜索一個(gè)給定的目標(biāo)值,如果數(shù)組中存在這個(gè)目標(biāo)值,則返回它的索引,否則返回 -1 。
你可以假設(shè)數(shù)組中不存在重復(fù)的元素。
你的算法時(shí)間復(fù)雜度必須是 O(log n)級別。
相關(guān)話題:?數(shù)組、二分查找????難度:?中等

示例1
輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出:4

示例2
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1

思路:
有序數(shù)組的二分查找時(shí),定義兩個(gè)指針lr,

  • 初始狀態(tài),l = 0r = nums.length - 1,在l <= r的條件下做循環(huán),每次折掉一半數(shù)據(jù);
  • 每次循環(huán)算出lr范圍內(nèi)中間的位置mid = l + ((r - l) >> 1),
    1.如果目標(biāo)值target == nums[mid],直接返回;
    2.如果target > nums[mid]target肯定在mid的右邊(更新l,l = mid + 1),否則在左邊(更新r,r = mid - 1)。

而我們這題的數(shù)組有可能發(fā)生了旋轉(zhuǎn),那么就不能單純依據(jù)targetnums[mid]的比較來判斷targetmid的左還是在右。

  • 左右部分有無序,分為三種情況:1.左無序,右肯定有序 2.右無序,左肯定有序 3.左右都有序,而判斷無序的條件是最左邊元素 > 最右邊元素
  • 如果左邊有序,那么就通過判斷target是否落在左邊來判斷target在左還是在右;如果右邊有序,那么就通過判斷target是否落在右邊來判斷target在左還是在右;反正,誰有序就用誰來判斷,因?yàn)榕袛鄺l件是最左邊元素 < target < 最右邊元素
class Solution {
    public int search(int[] nums, int target) {
        if(nums.length == 0) return -1;
        int l = 0, r = nums.length - 1;
        while(l <= r){
            int mid = l + ((r - l) >> 1);
            if(nums[mid] == target){
                return mid;
            }
            //左部分無序,右部分有序
            if(nums[l] > nums[mid]){
                if(target >= nums[mid] && target <= nums[r]){
                    l = mid + 1;
                }else{
                    r = mid - 1;
                }
                //右部分無序,左部分有序
            }else if(nums[mid] > nums[r]){
                if(target <= nums[mid] && target >= nums[l]){
                    r = mid - 1;
                }else{
                    l = mid + 1;
                }
                //左右部分都有序
            }else{
                if(target <= nums[mid] && target >= nums[l]){
                    r = mid - 1;
                }else{
                    l = mid + 1;
                }
            }
        }
        return -1;
    }
}

這里的mid也納入了左或右部分,而不是左:l->mid-1右:mid+1->r。這是為了減少邊界的處理。
以下代碼:左:l->mid-1,右:mid+1->r

class Solution {
    public int search(int[] nums, int target) {
        if(nums.length == 0) return -1;
        int l = 0, r = nums.length - 1;
        while(l <= r){
            int mid = l + ((r - l) >> 1);
            if(nums[mid] == target){
                return mid;
            }
            //左部分無序,右部分有序
            if(mid - 1 >= l && nums[l] > nums[mid - 1]){
                if(mid + 1 <= r && target >= nums[mid + 1] && target <= nums[r]){
                    l = mid + 1;
                }else{
                    r = mid - 1;
                }
                //右部分無序,左部分有序
            }else if(mid + 1 <= r && nums[mid + 1] > nums[r]){
                if(mid - 1 >= l && target <= nums[mid - 1] && target >= nums[l]){
                    r = mid - 1;
                }else{
                    l = mid + 1;
                }
                //左右部分都有序
            }else{
                if(mid - 1 >= l && target <= nums[mid - 1] && target >= nums[l]){
                    r = mid - 1;
                }else{
                    l = mid + 1;
                }
            }
        }
        return -1;
    }
}

由于判斷條件使用到mid - 1mid + 1的操作,可能會導(dǎo)致數(shù)組越界。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容