LeetCode-33.搜尋旋轉排序陣列(考察點:二分查詢)
阿新 • • 發佈:2019-02-13
題目描述:
假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。
( 例如,陣列 [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:
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
解法1:要求logn的時間複雜度,應該是要用二分法,但是由於所給排序陣列進行了一次旋轉,所以不能簡單的用二分法。
定義三個變數start、end、middle=(start+end)>>2,除了需判斷nums[middle]與target的大小之外,還需判斷nums[middle]與nums[start]、nums[end]的大小(以判斷target可能存在範圍是升序序列還是包含旋轉點)
程式碼:
class Solution { public int search(int[] nums, int target) { int start = 0, end = nums.length-1; while(start <= end){ if(target == nums[start]) return start; if(target == nums[end]) return end; int middle = (start + end)/2; if(target == nums[middle]) return middle; if(nums[start] > nums[middle]){ if(target > nums[middle] && nums[start] > target) start = middle + 1; else end = middle - 1; } else { if(target < nums[middle] && target > nums[start]) end = middle - 1; else start = middle + 1; } } return -1; } }
解法2:雖然用上面的解法做出來了,但是感覺太蠢了,就繼續找看有沒有更簡潔的做法,然後找到了一位大神的做法。
序列為兩個升序,給後面的升序(都小於第一個元素)加一個權值,使序列變為一個升序,然後二分查詢
程式碼:
class Solution { public int search(int[] nums, int target) { int start = 0, end = nums.length-1; while(start <= end){ int middle = (start + end) >> 1; if(target == nums[middle]) return middle; if(rightVal(target, nums[0]) > rightVal(nums[middle], nums[0])) start = middle + 1; else end = middle - 1; } return -1; } int rightVal(int x, int start){ return x < start ? x + 0x3f3f3f3f - start : x; } }
附大神的部落格:https://blog.csdn.net/bendaai/article/details/80059676