33. Search in Rotated Sorted Array

循環(huán)有序數(shù)組中查找一個元素,例如 [4,5,6,7,0,1,2] 中查找0七咧,要求復雜度 O(log(n)).

思路1:
一次二分查找卒蘸,但是比有序數(shù)組的二分查找邏輯復雜一點校辩。
// 在數(shù)組a的閉區(qū)間 [l,r] 內(nèi)查找 target
func bs(a []int, target int, l, r int) int {

  1. 首先查看區(qū)間是否合法, 如果 r < l, 直接返回-1
  2. r == l, 區(qū)間只有一個元素,只需判斷該元素是否為target
  3. 取區(qū)間中間元素 m = (l+r) / 2, 判斷 target落在哪個區(qū)間:
    1. target == a[m] 找到
    2. target > a[m] && target < a[l] 在右區(qū)間找 bs(a, target, m+1, r-1)
    3. target < a[m] && target > a[l] 在左區(qū)間找 bs(a, target, l+1, m-1)
    4. target > a[m] && target > a[l] 無法判定在左邊還是右邊區(qū)間找烛芬,需要確定 [l,m]是不是一個單調區(qū)間隧期,如果:
      a[l] < a[m] 則是一個單調區(qū)間,則在右區(qū)間找 bs(a, target, m+1, r-1)
      否則不是一個單調區(qū)間赘娄,則在左區(qū)間找 bs(a, target, l+1, m-1)
    5. target < a[m] && target < a[l] 同理仆潮,判斷是否單調區(qū)間:
      a[l] < a[m] 則是一個單調區(qū)間,則在右區(qū)間找 bs(a, target, m+1, r-1)
      否則不是一個單調區(qū)間遣臼,則在左區(qū)間找 bs(a, target, l+1, m-1)
      }

go代碼如下:沒有優(yōu)化性置,可能寫的比較啰嗦

func search(nums []int, target int) int {
    if len(nums) == 0 {
        return -1
    }
    return rs(nums, target, 0, len(nums)-1)
}

func rs(a []int, target, l,r int) int {
    if r < l {
        return -1
    }
    fmt.Println(a[l:r+1])
    if target == a[l] {
        return l
    }
    if target == a[r] {
        return r
    }
    if l == r {
        return -1
    }
    m := (l + r) / 2
    if target == a[m] {
        return m
    }
    
    switch {
    case target > a[m]:
        if target < a[l] {
            return rs(a, target, m+1, r-1)
        } else {
            if a[m] < a[l] {
                return rs(a, target, l+1, m-1)
            } else {
                return rs(a, target, m+1, r-1)
            }
        }
    default: // target < a[m]
        if target > a[l] {
            return rs(a, target, l+1, m-1)
        } else {
            if a[m] < a[l] {
                return rs(a, target, l+1, m-1)
            } else {
                return rs(a, target, m+1, r-1)
            }
        }
    }
}

思路2:
兩次二分查找
第一次先找拐點(數(shù)組最小值所在的點)。
第二次在正確的區(qū)間內(nèi)查找揍堰,找到最小值所在的點后鹏浅,兩個有序區(qū)間的范圍都清楚了,很容易判斷target落在哪個區(qū)間內(nèi)屏歹,然后在對應區(qū)間按照普通的二分查找進行查找就好了隐砸。

找最小值所在的點,遞歸收斂條件:a[l] < a[r] 即 [l,r]是一個有序區(qū)間蝙眶。
func bs(a []int, l, r int) int {
如果 l == r 或 a[l] < a[r], [l, r] 已經(jīng)是一個有序區(qū)間季希,返回l
如果 r - l == 1 則特殊判斷一下
// a[l] > a[r]
取中點 m = (l+r)/2
如果 a[m] < a[l],拐點應該在左區(qū)間 [l, m]幽纷;如果 a[m] >= a[l], 拐點應在右邊區(qū)間 [m, r]
}

go 代碼如下:

func search(nums []int, target int) int {
    if len(nums) == 0 {
        return -1
    }
    if target == nums[0] {
        return 0
    }
    m := findMin(nums, 0, len(nums)-1)
    if m == 0 {
        return bs(nums, target, 0, len(nums)-1)
    }
    if target > nums[0] {
        return bs(nums, target, 0, m-1)
    } 
    return bs(nums, target, m, len(nums)-1)
}

func findMin(a []int, l, r int) int {
    if l == r || a[l] < a[r] {
        return l
    }
    if r - l == 1 {
        if a[l] > a[r] {
            return r
        } 
        return l
    }
    // a[l] > a[r]
    m := (l+r)/2
    if a[m] < a[l] {
        return findMin(a, l, m)
    } else {
        return findMin(a, m, r)
    }
}

func bs(a []int, target int, l, r int) int {
    if r < l {
        return -1
    }
    m := (l + r) / 2
    if target == a[m] {
        return m
    }
    if target > a[m] {
        return bs(a, target, m+1, r)
    }
    return bs(a, target, l, m-1)
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末式塌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子友浸,更是在濱河造成了極大的恐慌峰尝,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收恢,死亡現(xiàn)場離奇詭異武学,居然都是意外死亡,警方通過查閱死者的電腦和手機派诬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門劳淆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來链沼,“玉大人默赂,你說我怎么就攤上這事±ㄉ祝” “怎么了缆八?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵曲掰,是天一觀的道長。 經(jīng)常有香客問我奈辰,道長栏妖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任奖恰,我火速辦了婚禮吊趾,結果婚禮上,老公的妹妹穿的比我還像新娘瑟啃。我一直安慰自己论泛,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布蛹屿。 她就那樣靜靜地躺著屁奏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪错负。 梳的紋絲不亂的頭發(fā)上坟瓢,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音犹撒,去河邊找鬼折联。 笑死,一個胖子當著我的面吹牛识颊,可吹牛的內(nèi)容都是我干的崭庸。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼谊囚,長吁一口氣:“原來是場噩夢啊……” “哼怕享!你這毒婦竟也來了?” 一聲冷哼從身側響起镰踏,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤函筋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奠伪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跌帐,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年绊率,在試婚紗的時候發(fā)現(xiàn)自己被綠了谨敛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡滤否,死狀恐怖脸狸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤炊甲,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布泥彤,位于F島的核電站,受9級特大地震影響卿啡,放射性物質發(fā)生泄漏吟吝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一颈娜、第九天 我趴在偏房一處隱蔽的房頂上張望剑逃。 院中可真熱鬧,春花似錦官辽、人聲如沸炕贵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽称开。三九已至,卻和暖如春乓梨,著一層夾襖步出監(jiān)牢的瞬間鳖轰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工扶镀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蕴侣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓臭觉,卻偏偏與公主長得像昆雀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蝠筑,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容