日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

漫画:删去k个数字后的最小值

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 漫画:删去k个数字后的最小值 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??漫畫:刪去k個數字后的最小值

?

?

我們來舉一個栗子:

給定整數?541270936,要求刪去一個數,讓剩下的整數盡可能小。

此時,無論刪除哪一個數字,最后的結果都是從9位整數變成8位整數。既然同樣是8位整數,我們顯然應該優先把高位的數字降低,這樣對新整數的值影響最大。

?

如何把高位的數字降低呢?很簡單,我們把原整數的所有數字從左到右進行比較,如果發現某一位的數字大于它右面的數字,那么在刪除該數字后,必然會使得該數位的值降低,因為右面比它小的數字頂替了它的位置。

在咱們這個例子中,數字5右側的數字4小于5,所以刪除數字5,最高位數字降低成了4。

?

?

?

?

?

?

?

?

?

?

/*** 刪除整數的k個數字,獲得刪除后的最小值* @param num ?原整數* @param k ?刪除數量*/public static String removeKDigits(String num, int k) {String numNew = num;for(int i=0; i<k; i++){boolean hasCut = false;//從左向右遍歷,找到比自己右側數字大的數字并刪除for(int j=0; j<numNew.length()-1;j++){if(numNew.charAt(j) > numNew.charAt(j+1)){numNew = numNew.substring(0, j) + numNew.substring(j+1,numNew.length());hasCut = true;break;}}//如果沒有找到要刪除的數字,則刪除最后一個數字if(!hasCut){numNew = numNew.substring(0, numNew.length()-1);}//清除整數左側的數字0numNew = removeZero(numNew);}//如果整數的所有數字都被刪除了,直接返回0if(numNew.length() == 0){return "0";}return numNew;}private static String removeZero(String num){for(int i=0; i<num.length()-1; i++){if(num.charAt(0) != '0'){break;}num = num.substring(1, num.length()) ;}return num;}public static void main(String[] args) {System.out.println(removeKDigits("1593212",3));System.out.println(removeKDigits("30200",1));System.out.println(removeKDigits("10",2));System.out.println(removeKDigits("541270936",3));}

小灰的代碼使用了兩層循環,外層循環基于刪除次數(k),內層循環從左到右遍歷所有數字。

當遍歷到需要刪除的數字時,利用字符串的自身方法subString() 把對應數字刪除,并重新拼接字符串。

顯然,這段代碼的時間復雜度是O(kn)。

?

結果,提交以后......

?

翻譯過來就是:恭喜你,打敗了16.56%的小伙伴!

?

?

1.每一次內層循環,都需要從頭遍歷所有數字

比如給定的整數是 11111111111114132,我們在第一輪循環中,需要遍歷大部分數字,一直遍歷到數字4,發現4>1,從而刪除4。

以目前的代碼邏輯,下一輪循環中,我們要從頭開始遍歷,再次重復遍歷大部分數字,一直遍歷到數字3,發現3>2,從而刪除3。

事實上,我們應該停留在上一次刪除的位置繼續進行比較。而不是從頭開始。

2.subString方法本身性能不高

subString方法的底層實現,涉及到了新字符串的創建,以及逐個字符的拷貝。這個方法自身的時間復雜度是O(n)。

因此,我們應該避免在每刪除以后數字后就調用subString方法。

?

?

?

/*** 刪除整數的k個數字,獲得刪除后的最小值* @param num ?原整數* @param k ?刪除數量*/public static String removeKDigits(String num, int k) {//新整數的最終長度 = 原整數長度 - kint newLength = num.length() - k;//創建一個棧,用于接收所有的數字char[] stack = new char[num.length()];int top = 0;for (int i = 0; i < num.length(); ++i) {//遍歷當前數字char c = num.charAt(i);//當棧頂數字大于遍歷到的當前數字,棧頂數字出棧(相當于刪除數字)while (top > 0 && stack[top-1] > c && k > 0) {top -= 1;k -= 1;}//遍歷到的當前數字入棧stack[top++] = c;}// 找到棧中第一個非零數字的位置,以此構建新的整數字符串int offset = 0;while (offset < newLength && stack[offset] == '0') {offset++;}return offset == newLength? "0": new String(stack, offset, newLength - offset);}public static void main(String[] args) {System.out.println(removeKDigits("1593212",3));System.out.println(removeKDigits("30200",1));System.out.println(removeKDigits("10",2));System.out.println(removeKDigits("541270936",3));}

代碼中非常巧妙地運用了棧的特性,在遍歷原整數的數字時,讓所有數字一個個入棧,當某個數字需要刪除時,讓該數字出棧。最后,程序把棧中的元素轉化為字符串結果。

我們仍然以整數 541270936,k=3 為例:

遍歷到數字5,數字5入棧:

?

遍歷到數字4,發現棧頂5>4,棧頂5出棧,數字4入棧:

?

遍歷到數字1,發現棧頂4>1,棧頂4出棧,數字1入棧:

?

繼續遍歷數字2,數字7,依次入棧。

?

遍歷數字0,發現棧頂7>0,棧頂7出棧,數字0入棧:

?

此時k的次數已經用完,無需再比較,剩下的數字一口氣入棧:

?

此時棧中的元素就是最終的結果。

代碼只對所有數字遍歷了一趟,遍歷的時間復雜度是O(n),而后把棧轉化為字符串的時間復雜度也是O(n),所以最終的時間復雜度是O(n)

同時,程序中利用棧來回溯遍歷過的數字以及刪除數字,所以程序的空間復雜度是O(n)

?

?

?

?

leetcode原題鏈接如下,有興趣的小伙伴可以自己嘗試哦:

https://leetcode.com/problems/remove-k-digits/description/

總結

以上是生活随笔為你收集整理的漫画:删去k个数字后的最小值的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。