來源:力扣(LeetCode) 連接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array算法
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。
搜索一個給定的目標值,若是數組中存在這個目標值,則返回它的索引,不然返回 -1 。
你能夠假設數組中不存在重複的元素。
你的算法時間複雜度必須是 O(log n) 級別。
示例 1:數組
輸入: nums = [4,5,6,7,0,1,2], target = 0 輸出: 4
示例 2:code
輸入: nums = [4,5,6,7,0,1,2], target = 3 輸出:
在讀完一遍題目以後呢,大致的感受是從數組中找到指定值的位置返回,沒有的話就返回-1。
而後我就直接寫下了排序
var search = function(nums, target) { return nums.indexOf(target); };
運行以後通了,提交以後也通了,執行時間68ms,內存消耗33.7MB。
完美的開始,不過在仔細審題以後,發現一個問題,題目要求複雜度必須是 O(log n)級別,那意思就是必須得使用二分法來作。那麼上面的答案就沒有意義了。
那麼從新開始思考。二分法很簡單,就是每次都二分數組,而後在符合條件的數組中進行下一步的二分查找。
將數組一分爲二以後,存在兩種可能,一邊是順序的,一邊是旋轉的,那麼就須要將target值與左右中間作間隔的值以及兩個數組的兩端值進行比較。從而判斷出要繼續在哪一個數組中繼續尋找。遞歸
實例 nums = [4,5,6,7,8,9,0,1,2], target = 0
//設置初試下標值: left=0; right = nums.length; mid = ~~((left + right)/2) //二分數組那麼這個時候mid=4 [4,5,6,7] 8 [9,0,1,2]
存在如下幾種狀況索引
中間值等於目標值,此時能夠直接返回mid內存
中間值比目標值target大而且左邊數組第一個值小於target,那麼說明左邊數組是存在旋轉的,而且目標值就在這個數組中,這個時候須要繼續在左邊數組中查找,這個時候left不變,right變成了mid-1;leetcode
中間值比目標值target小而且右邊數組最後一個值大於等於target,說明target值在右邊數組中,因此須要在右邊的數組中繼續查找。此時left變成了mid+1,right不變。get
這兩種狀況下,都是沒有肯定值在哪邊,因此講left+1或者right-1進行進一步的查找。
就這樣一步一步查找知道最終找到值。用遞歸能夠解決這個問題。io
因此代碼以下:
/** * @param {number[]} nums * @param {number} target * @return {number} */ var search = function(nums, target) { var bs = (left,right)=>{ const mid = ~~((left + right)/2); if(left > right)return - 1; if(nums[mid] === target){ return mid; }else if(nums[mid]>target && nums[left] <= target){ return bs(left,mid-1); }else if(nums[mid]>target && nums[left] > target){ return bs(left+1,right); }else if(nums[mid]<target && nums[right]>=target){ return bs(mid+1,right); }else if(nums[mid]<target && nums[right]<target){ return bs(left,right-1); } }; return bs(0,nums.length-1); };
運行結果: 執行時間:68ms 內存消耗:33.9MB