【LeetCode】402、移除K位數字


1、移除K位數字

題目:402. 移掉K位數字

題目描述:

  給定一個以字符串表示的非負整數 num,移除這個數中的 k 位數字,使得剩下的數字最小。(num 的長度小於 10002 且 ≥ k。
num 不會包含任何前導零。)

示例 :

    輸入: num = "1432219", k = 3
    輸出: "1219"
    解釋: 移除掉三個數字 4, 3, 和 2 形成一個新的最小的數字 1219。

    輸入: num = "10200", k = 1
    輸出: "200"
    解釋: 移掉首位的 1 剩下的數字為 200. 注意輸出不能有任何前導零。

    輸入: num = "10", k = 2
    輸出: "0"
    解釋: 從原數字移除所有的數字,剩余為空就是0。

解題思路:基於單調棧的貪心算法

  對於兩個長度相同的數字,其最左邊的數字決定了這兩個數字的大小,左邊的數字越小,數字也越小,比如如果由相同的元素組成的數字,升序序列是最小的。所以我們的想法是盡可能地使左邊的數字小

  所以,給定一個數字序列[a,b,c,d,e,f],如果數字b小於其左鄰居 a,則我們應該刪除左鄰居a,以獲得最小結果。

  對於每個數字,如果該數字小於棧頂部,即該數字的左鄰居,則彈出堆棧,即刪除左鄰居。否則,我們把數字推到棧上。
重復上述步驟,直到任何條件不再適用,例如堆棧為空(不再保留數字)。或者已經刪除了 k 位數字。

  同時,這里需要注意一些特殊情況:

  1、如果整個序列是單增的,我們會發現左鄰居永遠小,所以應該刪除掉末尾的k個數字即可。

  2、在完成整個循環后,棧中彈出的數字是逆序的,需要反轉,需要注意的是結果可能出現前導零,需要考慮到這種情況,將前導零刪除。

代碼實現:

class Solution {
    public String removeKdigits(String num, int k) {
        //基於單調棧的貪心思想
        if(k==0)
            return num;
        if(num.length()==0 || k>=num.length())
            return "0";
        
        Stack<Character> stack=new Stack<>();  //維護一個單調棧

        for(int i=0;i<num.length();i++){
            char c=num.charAt(i);
            while(!stack.isEmpty() && stack.peek()>c && k>0 ){  
                stack.pop();  //左邊的大則刪除,本質是貪心
                k--;
            }
            stack.push(c);
        }

        //特別注意:如果沒有刪夠k次,說明剩下的是單調不減的,則從末尾刪除即可
        for(int i=0;i<k;i++)  //剩余多少次由k決定
            stack.pop();

        //最后將棧中的元素彈出並反轉即可
        StringBuffer str=new StringBuffer();
        while(!stack.isEmpty()){
            str.append(stack.pop());
        }

        str=str.reverse(); //反轉

        //去除前導0
        int index=0;
        while(index<str.length() && str.charAt(index)=='0')
            index++;
        
        String res=str.toString().substring(index);
        
        return res.length()==0?"0":res;
    }
}

2、字典序最大的子序列

題目描述:

  給定⼀個字符串,得到它字典序最⼤的⼦序列。(換言之,也就是刪除⼀些字符,使得剩下的字符構成的字符串字典序是最⼤的)

解題思路:

  兩個字符串相比,字典序的大小首先是對排在前列的字符進行比較,越靠前的字符越大,整體的字典序就越大,因此,要想字典序最大,應該將其變為一個單調遞減的子序列

  因此,這和上一題實際上類似的,只是沒有了刪除k次的限制,同樣應該利用一個單調棧,當棧頂數字小於當前考察的元素時,即將其棧頂數字刪除,最后在棧中形成一個單調遞減(嚴格來說是單調不增)的子序列。

代碼實現

  與上題代碼基本類似,核心在於基於單調棧的貪心思想,越靠前的越大越好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM