成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

尋找旋轉數組中的最小數字

開發 前端
把一個數組最開始的若干個元素搬到數組的末尾,就稱之為數組的旋轉。有一個遞增排序數組,將其開頭的若干個元素移動至數組的末尾,尋找其中的最小值。

[[409450]]

本文轉載自微信公眾號「神奇的程序員K」,作者神奇的程序員K。轉載本文請聯系神奇的程序員K公眾號。

前言

把一個數組最開始的若干個元素搬到數組的末尾,就稱之為數組的旋轉。有一個遞增排序數組,將其開頭的若干個元素移動至數組的末尾,尋找其中的最小值。

本文就跟大家分享下如何用最快的速度找到遞增旋轉數組中的最小值,歡迎各位感興趣的開發者閱讀本文。

實現思路

乍一看這個問題,一部分開發者首先想到的解法就是從頭到尾遍歷下數組,這樣就能找出最小的元素。這種思路的時間復雜度是O(n),沒有將題目中的條件利用起來,因此這種方案不是本題的正確答案。

舉例分析

接下來,我們來分析下題目,通過舉例、觀察來尋找突破口。我們先來列舉一個遞增數組。

如上圖所示,我們準備了一個1 ~ 5的遞增數組,然后將其開頭的兩個元素搬到了數組的末尾,這樣就構成了一個旋轉數組。

經過一番觀察后,我們可以發現:

  • 旋轉后的數組可以劃分為兩個已經排序的小數組
  • 前面子數組的元素都大于等于后面子數組的元素
  • 最小的數字是這兩個子數組的分界線

二分查找

經過上面的分析,我們可知旋轉后的數組在一定程度上是排好序的,因此我們可以嘗試使用二分查找的思路來尋找最小的元素。

接下來,我們準備兩個指針(左指針、右指針),左指針指向數組的第一個元素,右指針指向數組的末尾元素,如下圖所示:

觀察上圖后,我們發現它們的中間元素是5、最小值在5的后面,因此我們就可以排除中間值之前的元素了,移動左指針至5,如下圖所示:

此時,它們的中間元素是1,我們發現最小值2的前面,因此我們就可以將右指針移動至中間1,如下所所示:圖片

最后,我們發現左指針與右指針相鄰,右指針指向的元素正好是旋轉數組的最小元素。

經過上述畫圖分析后,我們可以得到如下規律:

  • 如果兩個指針的中間元素大于等于左指針指向的元素,那么最小值一定在中間元素的后面,移動左指針至中間值位置縮小查找范圍
  • 如果兩個指針的中間元素小于等于右指針指向的元素,那么最小值一定在中間元素的前面,移動右指針至中間值位置縮小查找范圍
  • 左指針一定指向前面的遞增子數組,右指針一定指向后面的遞增子數組
  • 當左、右指針相鄰時,右指針所指向的元素就是這個數組的最小值

時間復雜度分析:每次移動指針,查找范圍都會縮小到原先的一半,因此總的時間復雜度為O(logn)

特殊情況

上述規律可以滿足大多數情況,當出現下述情況時我們就不能采用二分查找了:

  • 當數組的0號元素小于最后一個元素時,證明這個數組是排好序的,它的最小值是數組的第0號元素
  • 當左指針與右指針指向的元素相同且它們的中間元素也與其相同,那么就只能使用順序查找,如下圖所示:

實現代碼

接下來,我們根據上述所講內容來總結下思路:

  • 判斷數組是否已經排好序(第一個元素是否小于最后一個元素)
  • 左指針指向的值大于等于右指針指向的值就根據條件移動左、右指針:
    • 循環終止條件:左指針與右指針相鄰
    • 求左、右指針的中間索引
    • 左指針指向的值與右指針指向的值相同且中間元素也與之相同(使用順序查找 )
    • 中間值大于等于左指針指向的值,移動左指針位置至中間值位置
    • 中間值小于等于右指針指向的值,移動右指針位置至中間值位置
  • 循環結束,返回最小值

代碼如下所示:

  1. // 把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。 
  2. // 輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。 
  3. // 例如,數組[3,4,5,1,2]為[1,2,3,4,5]的一個旋轉,該數組的最小值為1。 
  4.  
  5. export default class FindWhirlingArrayMinVal { 
  6.   private leftPointer; 
  7.   private rightPointer; 
  8.   private middleIndex; 
  9.  
  10.   constructor() { 
  11.     this.leftPointer = 0; 
  12.     this.rightPointer = 0; 
  13.     this.middleIndex = 0; 
  14.   } 
  15.  
  16.   public getMinValue(incrementArray: Array<number>): number { 
  17.     this.rightPointer = incrementArray.length - 1; 
  18.     // 第一個元素小于最后一個元素,證明數組是排好序的 
  19.     if (incrementArray[this.leftPointer] < incrementArray[this.rightPointer]) { 
  20.       // 其最小值為第一個元素 
  21.       return incrementArray[this.leftPointer]; 
  22.     } 
  23.     while ( 
  24.       incrementArray[this.leftPointer] >= incrementArray[this.rightPointer] 
  25.     ) { 
  26.       // 循環終止條件: 右指針與左指針相鄰,最小值為右指針所指向的值 
  27.       if (this.rightPointer - this.leftPointer === 1) { 
  28.         this.middleIndex = this.rightPointer; 
  29.         break; 
  30.       } 
  31.       // 求中間值 
  32.       this.middleIndex = Math.floor((this.leftPointer + this.rightPointer) / 2); 
  33.       // 左指針指向的值與右指針指向的值相同且中間元素也與之相同 
  34.       // 則無法使用二分查找,需要順序查找 
  35.       if ( 
  36.         incrementArray[this.leftPointer] === 
  37.           incrementArray[this.rightPointer] && 
  38.         incrementArray[this.middleIndex] === incrementArray[this.leftPointer] 
  39.       ) { 
  40.         // 按順序查找 
  41.         let minValue = incrementArray[0]; 
  42.         for (let i = 0; i < incrementArray.length; i++) { 
  43.           if (incrementArray[i] < minValue) { 
  44.             minValue = incrementArray[i]; 
  45.           } 
  46.         } 
  47.         return minValue; 
  48.       } 
  49.  
  50.       if ( 
  51.         incrementArray[this.middleIndex] >= incrementArray[this.leftPointer] 
  52.       ) { 
  53.         // 中間值大于等于左指針指向的值 
  54.         // 移動左指針至中間值位置 
  55.         this.leftPointer = this.middleIndex; 
  56.       } else if ( 
  57.         incrementArray[this.middleIndex] <= incrementArray[this.rightPointer] 
  58.       ) { 
  59.         // 中間值小于等于右指針指向的值 
  60.         // 移動右指針至中間值位置 
  61.         this.rightPointer = this.middleIndex; 
  62.       } 
  63.     } 
  64.     // 循環結束,返回最小值 
  65.     return incrementArray[this.middleIndex]; 
  66.   } 

完整代碼請移步:findWhirlingArrayMinVal-test.ts

 

責任編輯:武曉燕 來源: 神奇的程序員K
相關推薦

2021-01-22 08:30:50

LeetCode數字數組

2022-05-27 13:45:38

區塊鏈數字鴻溝安全

2024-02-23 10:31:27

邊緣計算數字鴻溝XGAIN項目

2023-07-18 12:37:58

2021-01-14 08:23:15

LeetCode變量

2021-07-14 06:40:02

矩陣路徑字符串

2017-10-26 10:03:36

數據中心數字群集

2018-01-14 23:14:13

戴爾

2021-10-14 11:31:28

數組面試題中心下標

2012-08-10 09:59:47

2011-02-17 09:58:16

WindowsUbuntu

2017-05-22 10:54:56

深度學習CNNMNIST

2021-07-05 06:39:59

經典算法無序數組

2019-12-26 13:06:07

Windows 10旋轉屏幕Windows

2020-05-18 14:25:41

頻譜5G運營商

2017-11-13 09:38:30

數字化CIO轉型

2009-11-25 09:13:41

PHP數組轉字符串PHP字符串轉數組

2023-07-24 14:42:23

2014-10-13 17:04:28

IT運維管理

2017-12-26 14:27:24

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品一区二区三区在线播放 | 99热精品6| 久久久精品一区二区 | 精品乱子伦一区二区三区 | 亚洲性人人天天夜夜摸 | 久久久亚洲一区 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | 亚洲欧美自拍偷拍视频 | 亚洲一区二区中文字幕 | 精品视频一区二区三区 | 欧美黄色一区 | 一级毛片在线播放 | 国产欧美一区二区三区日本久久久 | 国产成人免费视频网站高清观看视频 | 精品伊人 | 久久成人综合 | 亚洲一区二区久久 | 黄色亚洲 | 国产成人久久精品一区二区三区 | 国产日韩欧美激情 | 性一区| 精品国产一区二区三区久久 | 黄色成人免费在线观看 | 久久久精品综合 | 中文字幕在线看人 | 中文在线亚洲 | 精品国产不卡一区二区三区 | 日日干夜夜草 | 在线视频99| 亚洲视频在线看 | 人人鲁人人莫人人爱精品 | 日韩日韩日韩日韩日韩日韩日韩 | 久操伊人 | 欧美a在线看 | 看毛片网站 | 欧美一二三 | 国产精品69久久久久水密桃 | 国产 欧美 日韩 一区 | 日韩欧美国产一区二区 | 日韩超碰| 精久久久 |