自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

尋找旋轉(zhuǎn)數(shù)組中的最小數(shù)字

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

[[409450]]

本文轉(zhuǎn)載自微信公眾號「神奇的程序員K」,作者神奇的程序員K。轉(zhuǎn)載本文請聯(lián)系神奇的程序員K公眾號。

前言

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

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

實現(xiàn)思路

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

舉例分析

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

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

經(jīng)過一番觀察后,我們可以發(fā)現(xiàn):

  • 旋轉(zhuǎn)后的數(shù)組可以劃分為兩個已經(jīng)排序的小數(shù)組
  • 前面子數(shù)組的元素都大于等于后面子數(shù)組的元素
  • 最小的數(shù)字是這兩個子數(shù)組的分界線

二分查找

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

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

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

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

最后,我們發(fā)現(xiàn)左指針與右指針相鄰,右指針指向的元素正好是旋轉(zhuǎn)數(shù)組的最小元素。

經(jīng)過上述畫圖分析后,我們可以得到如下規(guī)律:

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

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

特殊情況

上述規(guī)律可以滿足大多數(shù)情況,當出現(xiàn)下述情況時我們就不能采用二分查找了:

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

實現(xiàn)代碼

接下來,我們根據(jù)上述所講內(nèi)容來總結(jié)下思路:

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

代碼如下所示:

  1. // 把一個數(shù)組最開始的若干個元素搬到數(shù)組的末尾,我們稱之為數(shù)組的旋轉(zhuǎn)。 
  2. // 輸入一個遞增排序的數(shù)組的一個旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素。 
  3. // 例如,數(shù)組[3,4,5,1,2]為[1,2,3,4,5]的一個旋轉(zhuǎn),該數(shù)組的最小值為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.     // 第一個元素小于最后一個元素,證明數(shù)組是排好序的 
  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.       // 循環(huán)終止條件: 右指針與左指針相鄰,最小值為右指針所指向的值 
  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.     // 循環(huán)結(jié)束,返回最小值 
  65.     return incrementArray[this.middleIndex]; 
  66.   } 

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

 

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

2021-01-22 08:30:50

LeetCode數(shù)字數(shù)組

2022-05-27 13:45:38

區(qū)塊鏈數(shù)字鴻溝安全

2024-02-23 10:31:27

邊緣計算數(shù)字鴻溝XGAIN項目

2023-07-18 12:37:58

2021-01-14 08:23:15

LeetCode變量

2017-10-26 10:03:36

數(shù)據(jù)中心數(shù)字群集

2018-01-14 23:14:13

戴爾

2021-07-14 06:40:02

矩陣路徑字符串

2021-10-14 11:31:28

數(shù)組面試題中心下標

2012-08-10 09:59:47

2011-02-17 09:58:16

WindowsUbuntu

2021-07-05 06:39:59

經(jīng)典算法無序數(shù)組

2017-11-13 09:38:30

數(shù)字化CIO轉(zhuǎn)型

2017-05-22 10:54:56

深度學習CNNMNIST

2009-11-25 09:13:41

PHP數(shù)組轉(zhuǎn)字符串PHP字符串轉(zhuǎn)數(shù)組

2019-12-26 13:06:07

Windows 10旋轉(zhuǎn)屏幕Windows

2018-05-09 12:27:34

Linux命令尋找文件

2023-07-24 14:42:23

2009-04-09 10:17:00

2014-10-20 11:14:43

點贊
收藏

51CTO技術(shù)棧公眾號