11. 旋轉數組的最小數字

2021-02-21 incipe
原題

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。

例如,數組 [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

思路

這是一道二分查找的變種題,數組被分成了兩個部分,每個部分都是有序的,要求查找數組的最小值,時間複雜度

當然

二分查找Ⅰ. 基本模板
int binary_search(vector<int> &vec, int target) {
  int low = 0, high = vec.size() - 1;
  while (low <= high) {
    int mid = low + (high - low) / 2;
    if (vec[mid] > target) {
      high = mid - 1;
    } else if (vec[mid] < target) {
      low = mid + 1;
    } else {
      return mid;
    }
  }
  return -1;
}

或者

int binary_search(vector<int> &vec, int target) {
  int low = 0, high = vec.size() - 1;
  while (low < high) {
    int mid = low + (high - low) / 2;
    if (vec[mid] > target) {
      high = mid;
    } else if (vec[mid] < target) {
      low = mid + 1;
    } else {
      return mid;
    }
  }
  return -1;
}

Ⅱ. 題目分析

這道題還是有意思的,題目並沒有說數組中不包含重複元素,那就是可能存在重複元素,加上這個題目就不那麼簡單了。

我們定義

任何一個旋轉數組,肯定會被

我們怎麼判斷這這個旋轉數組哪個部分有序呢?通過比較

還剩下幾個問題:

如果 說明右邊有序,所以我們可以判斷最小值肯定在

如果 說明左邊有序,但是因為題目給的旋轉數組的定義( 把一個數組最開始的若干個元素搬到數組的末尾 ),我們可以肯定最小元素在數組右邊

如果我們用

比如:

當 時,我們通過縮小判斷範圍來解決,即

參考 面試題 11. 旋轉數組的最小數字(二分法,清晰圖解)[1]

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int size = numbers.size();
        int left = 0, right = size - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (numbers[mid] < numbers[right]) {
                right = mid;
            } else if (numbers[mid] > numbers[right]) {
                left = mid + 1;
            } else {
                --right;
            }
        }
        return numbers[left];
    }
};
// 這樣寫也是可以的~
// class Solution {
// public:
//     int findMin(vector<int>& nums) {
//         int size = nums.size();
//         int left = 0, right = size - 1;
//         int ans = INT_MAX;
//         while (left <= right) {
//             int mid = left + (right -left) / 2;
//             if (nums[mid] < nums[right]) {
//                 ans = min(ans, nums[mid]);
//                 right = mid - 1;
//             } else if (nums[mid] > nums[right]) {
//                 left = mid + 1;
//             } else {
//                 --right;
//             }
//         }
//         return min(ans, nums[left]);
//     }
// };

class Solution:
    def minArray(self, numbers: List[int]) -> int:
        left, right = 0, len(numbers) - 1
        while left < right:
            mid = (left + right) // 2
            if numbers[mid] < numbers[right]:
                right = mid
            elif numbers[mid] > numbers[right]:
                left = mid + 1
            else:
                right -= 1
        return numbers[left]

總結

這個題還是比較難的,值得思考,初次遇到估計很難想到,細節太多了。

相似的題

33. 搜索旋轉排序數組[2]

153. 尋找旋轉排序數組中的最小值[3]

如果理解了怎麼壓縮邊界,縮小範圍,這兩道題肯定就是很簡單的了。這兩道題都是數組中不包含重複元素的!!!

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int size = nums.size();
        int left = 0, right = size - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > nums[right]) {
                // 說明左邊有序,看看要查找的target在不在左邊,因為是有序的,所以只要滿足 nums[left] <= target < nums[mid]
                // 就能確定target在左邊了,否則,就不在左邊,要去右邊找。
                if (nums[mid] > target && target >= nums[left]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } else {
                // 說明右邊有序,同左邊有序,判斷target在不在右邊,在右邊就在右邊找,不在就在左邊找。
                if (nums[mid] < target && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
};

class Solution {
public:
    int findMin(vector<int>& nums) {
        int size = nums.size();
        int left = 0, right = size - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < nums[right]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return nums[left];
    }
};

參考[1]

面試題 11. 旋轉數組的最小數字(二分法,清晰圖解): https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/solution/mian-shi-ti-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-3/

[2]

33. 搜索旋轉排序數組: https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

[3]

153. 尋找旋轉排序數組中的最小值: https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/

- END -

相關焦點

  • 【ADAMS】矩陣/數組函數
    (1)矩陣/數組的基本操作函數ALIGN 將數組轉換到從特定值開始ALLM 返回矩陣元素的邏輯值ANGLES 將方向餘弦矩陣轉換為指定旋轉順序下的角度矩陣ATAN(x) 數字表達式x 的反正切值ATAN2(x1,x2) 兩個數字表達式x1,x2 的四象限反正切值(3)取整函數INT(x)
  • Excel VBA如何定義數組,這裡有最全的數組定義方法
    Dim + 數組名定義數組用Dim關鍵字,後面的一些參數,沒有也可以,表示任意大小或任意類型的數組。Dim Arr(0 to 10)這樣就定義了一個由最小下標為0,最大下標為10的一維數組,也就是Arr數組裡面包含了從0~10的11個變量。
  • 圖解NumPy,這是理解數組最形象的一份教程了
    數據表示考慮所有需要處理和構建模型所需的數據類型(電子表格、圖像、音頻等),其中很多都適合在 n 維數組中表示:表格和電子表格電子表格或值表是二維矩陣。電子表格中的每個工作表都可以是它自己的變量。python 中最流行的抽象是 pandas 數據幀,它實際上使用了 NumPy 並在其之上構建。
  • 怎麼理解php中的數組?php的數組創建和使用方法是什麼?
    數組中的元素是什麼?在數組中每一個值叫做數組的元素。也可以在方括號使用索引添加新元素,或者把新的值賦給已知數組元素。$myarray[3]=『four』;數組的創建方法PHP中,創建數組最簡單的辦法是使用array命令如下:$myarray=array(『one』,2,『three』);這段代碼是創建了一個叫$my array的數組,它包含了三個值:『one』,2,『three』,在這個數組中第一個和第三個包含了字符串,而第二個包含了一個數字。
  • LeetCode145|數組中數字出現的次數II
    一,數組中數字出現的次數II1,問題描述在一個數組 nums 中除一個數字只出現一次之外,其他數字都出現了三次
  • Excel中的高科技:數組公式之數組常量
    Excel中的高科技:數組公式之數組常量大家好,我是@愛玩電腦,不會IT高科技,只講電腦小知識。上次給大家講了辦公軟體Excel數組公式的一些基礎知識,見:Excel中的高科技:數組公式。今天接著給大家講講辦公軟體Excel中的數組公式相關的數組常量的基礎知識。好了,我們開始進入主題吧。演示的作業系統為Windows10,辦公軟體為Excel2007。一、創建數組常量在Excel中,數組並不是必須存儲在單元格中,也可以存儲在內存中。
  • 數字能量手機號碼中處事靈活卻情緒壓抑的數組?
    工作生活,本身都有壓力,很多時候,一定的壓力,卻是無形的動力,每個人都有自己的處事風格,不管是哪種風格,都是自我的展現,只是有一種現象,做事很靈活,左右逢源,但是,內心卻很苦悶,或者說,內心比較壓抑,比如,數組8388,數字能量手機號碼中,數組8388是由83/38
  • 一起學JAVA——數組和函數
    今天我們高級數據類型——數組以及函數的作用。函數(方法)函數的定義函數就是一段有名字的代碼,可以完成某一特定功能。方法(函數)是java的最小代碼重用單位,方法(函數)是為了重用代碼。如果不需要參數也要寫小括號,如果沒有返回值類型要寫void。名詞解釋形參:在定義函數時小括號中的參數,用來接收數據的參數。實參:在調用函數時真正傳入的參數,傳遞給函數的數據。
  • LeetCode數組類知識點&題型總結
    數組(array)就是典型的順序存儲,而鍊表就是典型的非順序存儲。數組通常用於存儲一系列相同類型的數據。當我們在創建數組時,會在內存中劃分出一塊連續的內存用於存儲數據,插入數據時,會將數據按順序存儲在這塊連續的內存中,讀取時通過訪問數組的索引迅速取出。數組名就是一個指針,指向這段內存的起始地址。通過數組的類型,編譯器知道在訪問下一個元素的時候需要在內存中後移多少個字節。
  • LeetCode刷題第三周【數組(簡單)】
    第 k 個缺失的正整數[3]題目要求:給你一個 嚴格升序排列 的正整數數組 arr 和一個整數 k 。示例 1:輸入:arr = [2,3,4,7,11], k = 5輸出:9解釋:缺失的正整數包括 [1,5,6,8,9,10,12,13,...] 。第 5 個缺失的正整數為 9 。
  • 如何使用Numpy數組?
    【連續「Python利用Numpy數組進行數據處理(一)」】2.【聚合函數】數學和統計方法[軸和0]可以通過數組上的一組數學函數對整個數組或某個軸向的數組進行統計計算。零長度的數組的mean為NaNstd、var分別為標準差和方差,自由度可調(默認為n)min、max最小值和最大值argmin、argmax分別為最小和最大元素的索引cumsum所有元素的累計和sumprod所有元素的累計積3.用於布爾型數組的方法
  • 了解什麼是數組,如何應用數組,只需1分鐘就可以秒變數組大神!
    第一個公式={Sum(2*4,3*2)} =Sum(8,6)=14第二個公式={Sum(2+4,3+2,) }=Sum(6,5)=11看了這些,你應該可以稍微理解了什麼是數組了,數組是怎麼運算的。接下我們順便說下什麼是常數數組,這個在後面會用到,也是一個非常重要的概念。我們可以在數組中使用常數值,這些值可以放在數組公式中使用區域引用的地方。
  • NumPy數組中的廣播機制及結構化數組
    廣播機制廣播機制這一操作實現了對兩個或以上數組進行運算或用函數處理,即使這些數組形狀並不完全相同。並不是所有的維度都要彼此兼容才符合廣播機制的要求,但它們必須要滿足一定的條件。前面講過,在NumPy中,如何通過用表示數組各個維度長度的元素(也就是數組的型)把數組轉換成多維數組。因此,若兩個數組的各維度兼容,也就是兩個數組的每一維等長,或其中一個數組為一維,那麼廣播機制就適用。如果這兩個條件都不能滿足,NumPy就會拋出異常,說這兩個數組不兼容。執行完代碼之後,我們就得到了兩個數組:4x4的數組以及一個一行四列的數組。
  • 「LeetCode算法精講」數組中的最短無序連續子數組(Python)
    題目內容給定一個整數數組,你需要尋找一個連續的子數組,如果對這個子數組進行升序排序,那麼整個數組都會變為升序排序。你找到的子數組應是最短的,請輸出它的長度。說明:輸入的數組長度範圍在 [1, 10,000]。輸入的數組可能包含重複元素 ,所以升序的意思是<=。
  • NumPy的數組對象
    一、創建數組可以有多種方式創建NumPy數組:(1)使用NumPy的array函數從Python列表中創建數組,數組類型由列表中的數據類型確定;(2)使用NumPy的zeros函數創建數組元素全部為0的數組,默認情況下數組元素的類型為float64;(3)使用NumPy的ones函數創建數組元素全部為1的數組,默認情況下數組元素的類型為float64;(4)使用NumPy
  • Numpy的ndarray:一種多維數組對象
    前言Numpy最重要的一個特點就是其N維數組對象(即ndarray),該對象是一個快速而靈活的大數據集容器。可以利用這種數組對整塊數據執行一些數學運算。模塊導入方式如下:import numpy as npndarray是一個通用的同構數據多維容器,也就是說,其中的所有元素必須是相同類型的。
  • Maximum Sum Circular Subarray 環形子數組的最大和
    Example 5:Input: [-2,-3,-1]Output: -1 Explanation: Subarray [-1] has maximum sum -1Note:-30000<=A[i]<=300001<=A.length<=30000這道題讓求環形子數組的最大和
  • 像數組又不是數組:JS函數的參數列表到底是什麼?
    但在實際使用過程中它的使用方式和數組簡直一模一樣,用起來感覺就是數組,沒有任何毛病,但實際上它並不是一個數組。arguments看起來,用起來都像是數組1 調用方法類似:都可以通過中括號下標的形式來訪問具體某個參數。
  • Sort an Array 數組排序
    題目給定了每個數字的範圍是 [-50000, 50000],並不是特別大,這裡可以使用記數排序 Count Sort,在 LeetCode 中也有直接利用這個解法的題Sort Colors,建立一個大小為 100001 的數組 count,然後統計 nums 中每個數字出現的個數,然後再從0遍歷到 100000,對於每個遍歷到的數字i,若個數不為0,則加入 count 數組中對應個數的 i-50000
  • Number of Squareful Arrays 平方數組的個數
    的全排列數組是個平方數組。其實這道題有兩個難點,一個是如何求全排列,另一個是如何在生成全排列的過程中驗證平方數組。LeetCode 有好幾道關於全排列的題,比較基本的就是這兩道 Permutations 和 Permutations II,很明顯這道題中的數字是有可能重複的,所以跟後者更接近。其實這道題的解法就是基於 Permutations II 來做的,只不過在過程中加入了判斷平方數組的步驟。