漫畫演算法 學習筆記(25)

2021-10-22 10:28:50 字數 3100 閱讀 1324

方法二(貪心演算法+單調棧)

q: 給出乙個整數,從該整數中去掉k個數字,要求剩下的數字形成的新整數盡可能小。

其中整數的長度大於或等於k,給出的整數的大小可以超過long型別的數字範圍。

示例1:

給定整數為1593212 ,刪去3個數字,新整數最小的情況為1212

給定整數為30200,刪去1個數字,新整數最小的情況是200

給定整數為10,刪去2個數字(注意這裡刪除的是2個數字),新整數的最小情況是0

給定整數為1432219,刪去3個數字,新整數的最小情況是1219

方法一(貪心演算法)

思路對於兩個相同長度的數字序列,最左邊不同的數字決定了這兩個數字的大小,例如,對於a=1a***,b=1b***,如果a>b則a>b。基於此,我們可以知道,若要使得剩下的數字最小,需要保證靠前的數字盡可能小。

舉個例子

給出乙個整數541270936,要求刪去1個數字,讓剩下的整數盡可能小。

此時,無論刪除哪乙個數字,最後的結果都是從9位整數變成8位整數。既然同樣是8位整數,顯然應該有限吧高位的數字降低,這樣對新整數的值影響最大。

如何把高位的數字降低呢?很簡單,**把原整數的所有數字從左到右進行比較,如果發現某一位數字大於它右面的數字,那麼在刪除該數字後,必然會使該數字的值降低。**因為右面比它小的數字頂替了它的位置。在上面的例子中,數字5右側的數字4<5,所以刪除數字5,最高位數字降低成了4。

對於整數541 270 936 ,刪除乙個數字所能得到的最小值是41 270 936 。那麼對於41 270 936 ,刪除乙個數字的最小值,是多少呢?

從左到右遍歷,數字4是第1個比右側數字大的數(4>1).

對於整數1 270 936 中再刪除乙個數字,得到中最小值是多少呢? 因為1<2 ,2<7,7>0 所以被刪除的數字因為7.

因此原數541 270 936 ,刪除3個數字後的最小值,新數字的最小值為 120 936

像這樣依次求得區域性最優解,最終得到全域性最優解的思想,叫作貪心演算法

時間複雜度

因為每一次迴圈都需要從頭開始遍歷所有的數字,需要經歷k輪迴圈。因此時間複雜度為o(kn)。

**實現

/**

* 刪除整數的k個數字,獲得刪除後的最小值

* param num 原整數

* param k 刪除數量

*/public

static string removekdigits

(string num,

int k)

}// 如果沒有找到要刪除的數字,則刪除最後乙個數字if(

!hascut)

}//清除整數左側的數字0

int start =0;

for(

int j=

0;jlength()

-1;j++

) start++;}

num =num.

substring

(start.num.

length()

);//如果整數的所有陣列都被刪除了,直接返回0

if(num.

length()

==0)return num;

}public

static

void

main

(string[

] args)

方法二(貪心演算法+單調棧)

思路繼續沿用方法一的思想,不過這裡我們要做一些優化,方法一採用的是以k作為外迴圈,遍歷數字作為內迴圈,需要額外考慮的東西很多。我們可以換乙個思路,以遍歷數字作為外迴圈,以k最為內迴圈,並引入棧來輔助我們處理。

因此,對於每個數字,如果該數字小於棧頂元素,我們就不斷地彈出棧頂元素,直到

此外,我們還需要注意以下幾個點:

時間複雜度

這樣一來,我們只會對所有數字遍歷一次,遍歷的時間複雜度為o(n),把棧轉化為字串的時間複雜度也是o(n),所以最終的時間複雜度為o(n)。

**實現

/**

* 刪除整數的k個數字,獲得刪除後的最小值

* param num 原整數

* param k 刪除數量

*/public

static string removekdigits

(string num,

int k)

//遍歷到的當前數字入棧

stack[top++

]=c;

}// 找到棧中第1個非零數字的位置,以此構建新的整數字串

int offset =0;

while

(offset =='0'

)return offset==newlength ?

"0":

newstring

(stack,offset,newlength-offset);}

public

static

void

main

(string[

] args)

golang實現
func

removekdigits

(num string

, k int

)string

//遍歷原數列

for i :=

range num

// 遍歷到的當前數字入棧

stack=

(stack,digit)

}// 獲取擷取之後的棧

stack=stack[

:len

(stack)

-k]// 刪除數字中包含前導為0的數字

digits :=strings.

trimleft

(string

(stack)

,"0"

)// 如果最終的字串為 空 返回 0

if digits==

""return digits

}func

main()

漫畫演算法 學習筆記01

在計算機領域裡,演算法是一系列程式指令,用於處理特定的運算和邏輯問題。衡量演算法優劣的主要標準是時間複雜度和空間複雜度。資料結構是資料的組織 管理和儲存格式,其使用目的是為了高效的訪問和修改資料。資料結構包含陣列 鍊錶這樣的線性資料結構,也包含樹 圖這樣的複雜資料結構。資料結構 data struc...

漫畫演算法 學習筆記(03)

3.實現 4.陣列與鍊錶的比較 鍊錶 linked list 是一種在物理上非連續 非順序的資料結構,由若干節點 node 所組成。private static class node 鍊錶的第乙個節點被稱為頭節點,最後乙個節點被稱為尾節點,尾節點的next指標指向null。對於鍊錶的其中乙個節點a,...

漫畫演算法 學習筆記(11)

2.二叉堆堆自我調整 3.二叉堆的 實現 二叉堆 本質上是一種完全二叉樹,它分兩個型別。什麼是最大堆?最大堆 最大堆的任何乙個父節點的值,都大於或等於它左 右孩子節點的值。什麼是最小堆?最小堆 最小堆的任何乙個父節點的值,都小於或等於它左 右孩子節點的值。二叉堆的根節點叫作堆頂。最大堆和最小堆堆特點...