剑指offer 11. 旋转数组的最小数字(很详细!)
劍指offer 11. 旋轉數組的最小數字
- 題目
- 解題思路
- 代碼
題目
解題思路
一開始,我們就能直接想到,數組找最小值,那么不輕輕松松直接遍歷一遍,用一個變量記錄最小值,然后直接返回不就完事了?
但是這樣做真的不優雅!!!,因為題目已經說了是一個旋轉的數組,直接遍歷暴力,那么題目還要說旋轉干嘛呢?
所以這里我們需要具體分析一下可以包含重復元素的數組旋轉過后會是什么情況
旋轉過后基本上是這種圖案:最小值大概位于中間位置(這里偷點懶直接用了力扣官方的圖片,懶得畫圖了😁)
注意到,旋轉數組中的最后一個值x, 在最小值右側的值都小于等于x,在最小值左側的值都大于等于x,因此根據這一條性質,我們可以使用二分查找找出數組中的最小值
我們將在二分查找的每一步中,左邊界為 low,右邊界為high,區間的中點為 pivot,最小值就在該區間內。
我們將中軸元素 numbers[pivot]與右邊界元素 numbers[high] 進行比較,可能會有以下的三種情況:
-
1.第一種情況是numbers[pivot] < numbers[high] 那么就是這樣的
說明最小值位于pivot的左邊那么我們可以將右邊界high縮小為pivot所指的地方 即 high = pivot -
第二種情況 numbers[pivot] > numbers[high] ,那么就是這樣
說明numbers[pivot]是最小值左側的元素我們將low更新為 pivot + 1
即low = povit + 1
這里說明一下為什么是更新為povit + 1 而上面的情況是更新為povit
因為numbers[pivot] > numbers[high]時,pivot只可能在最小值左側,pivot+1最大只能是最小值的位置。但是,numbers[pivot] < numbers[high]時,pivot既可能剛好是最小值,也可能在最小值右側,如果剛好是最小值的話,pivot-1就錯過了最小值. -
第三種情況是 numbers[pivot] == numbers[high] :
由于數組中可能存在重復的元素那么可能的情況是這樣的
由于數組中可能存在重復的元素,我們無法確定pivot是位于最小值的左側還是右側.所以我們不能莽撞的去忽略任何一部分的值.但是我們唯一可以確認的是
不管high指向的值是不是最小值,我們都有一個替代值就是pivot.
所以我們可以忽略右端點
即 : high--
知道了思路我們就可以寫代碼了
代碼
func minArray(numbers []int) int {low := 0high := len(numbers) - 1for low < high {povit := low + (high - low)/2if numbers[pivot] < numbers[high] {high = pivot}else if numbers[pivot] > numbers[high]{low = pivot + 1}else {high--}}return numbers[low] }時間復雜度 : O(logn) n為numbers的長度,特殊案例時[1,1,1,1]會退化為O(n)
要遍歷n次
空間復雜度 : O(1) : low,high,pivot變量使用常數大小的額外空間。
這里使用的是go語言寫的,其他語言也差不多啦,解題思路都是一樣的
總結
以上是生活随笔為你收集整理的剑指offer 11. 旋转数组的最小数字(很详细!)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 中 a = a++ 的分析
- 下一篇: 使用gin和gorm框架完成的bubbl