1. 程式人生 > 實用技巧 >旋轉陣列的最小數字(Python and C++解法)

旋轉陣列的最小數字(Python and C++解法)

題目:

  把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如,陣列[3,4,5,1,2] 為 [1,2,3,4,5] 的一個旋轉,該陣列的最小值為1。

示例 1:

輸入:[3,4,5,1,2]
輸出:1

示例 2:

輸入:[2,2,2,0,1]
輸出:0

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

思路:

  本題需要對二分查詢法靈活運用。本題沒有明確的目標值進行比較,可以將端點numbers[right]看作目標值,進而進行區間判斷。

  在正常情況下,對於旋轉之後的陣列,前面的子陣列元素都>=後面的子陣列元素,且最小的元素就是這兩個子陣列的分界點。

  特殊情況一:搬移了0個元素,即旋轉之後的陣列還是原來的遞增陣列,此時陣列的特點是numbers[left] <numbers[right].

  特殊情況二:numbers[mid] == numbers[right]時,若陣列是[1,0,1,1,1]或[1,1,1,0,1],則不能確定最小值在左邊還是在右邊,只能一步步改變邊界,慢慢縮小範圍。

注意:不能把左端點看做目標值,原因在於這樣不能確定最小值在哪一側:
情況1 :1 2 3 4 5 , arr[mid] = 3. target = 1, arr[mid] > target, 答案在mid 的左側

情況2 :3 4 5 1 2 , arr[mid] = 5, target = 3, arr[mid] > target, 答案卻在mid 的右側

Python解法:

 1 class Solution:
 2     def minArray(self, numbers: List[int]) -> int:
 3         left = 0
 4         right = len(numbers) - 1
 5 
 6         if numbers[left] < numbers[right]:  # 特殊情況,旋轉0個元素,旋轉前後不變
 7             return
numbers[left] 8 9 while left <= right: 10 mid = left + ((right - left) >> 1) 11 if numbers[mid] < numbers[right]: 12 right = mid # numbers[mid]可能是最小值,所以右邊界不能變 13 elif numbers[mid] > numbers[right]: 14 left = mid + 1 15 else: # 二者相等時,在特殊情況[1,0,1,1,1]或[1,1,1,0,1]時不能確定最小值在左還是在右 16 right -= 1 # 只能一步步更新right,慢慢縮小範圍 17 return numbers[left]

C++解法:

 1 class Solution {
 2 public:
 3     int minArray(vector<int>& numbers) {
 4         int left = 0;
 5         int right = numbers.size() - 1;
 6 
 7         if(numbers[left] < numbers[right])  // 特殊情況一
 8             return numbers[left];
 9 
10         while(left <= right) {
11             int mid = left + ((right - left) >> 1); 
12             if(numbers[mid] < numbers[right])
13                 right = mid;
14             else if(numbers[mid] > numbers[right])
15                 left =  mid + 1;
16             else  // 特殊情況二
17                 right -= 1;
18         }
19         return numbers[left];  // 需要返回左端點
20     }
21 };