【LeetCode-查詢】旋轉陣列的最小數字
阿新 • • 發佈:2020-07-22
題目描述
把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如,陣列 [3,4,5,1,2] 為 [1,2,3,4,5] 的一個旋轉,該陣列的最小值為1。
示例:
輸入:[3,4,5,1,2]
輸出:1
輸入:[2,2,2,0,1]
輸出:0
題目連結: https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/
思路
使用二分查詢來做。陣列可以分為兩個部分,左邊的元素都大於等於右邊的元素。
- 初始化 left 和 right 兩個指標,left = 0, right = num.size()-1;
- 如果 left<right,迴圈:
- mid = (left+right)/2;
- 如果 nums[mid]>nums[right],說明當前 mid 在左邊,則更新 left = mid+1;
- 如果 nums[mid]<nums[left],說明當前 mid 在右邊,則更新 right = mid;
- 如果 nums[mid]==nums[right],此時無法判斷 mid 在左邊還是右邊,則 right-- 縮小範圍;
- 最後返回 nums[left]。
需要注意的是,我們判斷 nums[mid]>nums[right],而不是 nums[mid]>nums[left],原因是隻靠 nums[mid]>nums[left] 無法判斷 mid 在左邊還是在右邊,而 nums[mid]>nums[right] 可以確定 mid 在哪一邊;使用 nums[mid]<nums[left] 也是一樣的原因。
這題我覺得難點除了上面說的判斷條件之外,還有一點是這題不符合二分查詢的常規寫法。在常規的二分查詢中,如果 right 初始化為 nums.size()-1 的話,迴圈條件應該是 left<=right,right的更新方式應該是 right = right-1,但這題不是,需要注意一下。
程式碼如下:
class Solution { public: int minArray(vector<int>& numbers) { int left = 0; int right = numbers.size()-1; while(left<right){ if(left==right) return numbers[left]; int mid = left + (right - left) / 2; if(numbers[mid]>numbers[right]) left = mid + 1; else if(numbers[mid]<numbers[left]) right = mid; else right--; } return numbers[left]; } };
- 時間複雜度:O(log n)
- 空間複雜度:O(1)