Leetcode-402Remove K Digits

402. Remove K Digits

Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.

Note:
The length of num is less than 10002 and will be ≥ k.
The given num does not contain any leading zero.
Example 1:

Input: num = "1432219", k = 3
Output: "1219"

Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2:

Input: num = "10200", k = 1
Output: "200"

Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3:

Input: num = "10", k = 2
Output: "0"

Explanation: Remove all the digits from the number and it is left with nothing which is 0.

題解:

非負(fù)整數(shù)num,移除num中的k個數(shù)字后移迫,求所能得到的最小的數(shù)是多少;
輸入的是一個字符串表示的num和要去除的數(shù)字的個數(shù)k:
例如題中所給的例1:
輸入: num = "1432219", k = 3
1432219去除3個數(shù)字后得到的最小的數(shù)為1219运准;
輸出: "1219"

分析:

如何能夠保證刪除數(shù)字后所得到的數(shù)最小呢利职?
不難想到违诗,最小的數(shù)牧牢,它的最高位一定要盡可能的取最小的揖膜,次高位盡可能的取最高位后面最小的誓沸,直到刪除的數(shù)的個數(shù)為k為止;
以num = "1432219", k = 3為例:

  1. 考慮第一位數(shù)字1壹粟,分為兩種可能:
    刪除1:(1)432219 :刪除1的話我們可以得到432219拜隧;
    不刪除1:1 (432219):不刪除1的話我們需要在432219中刪除一個數(shù)字;
    不難看出趁仙,無論后續(xù)刪除432219中的哪個數(shù)字洪添,1xxxxx 始終小于 432219;所以保留1為最優(yōu)策略雀费。
  2. 考慮第二位數(shù)字4,分為兩種可能:
    刪除4:1(4)32219 :刪除4的話我們可以得到132219盏袄;
    不刪除4:14(32219):不刪除4的話我們需要在32219中刪除一個數(shù)字忿峻;
    不難看出,無論后續(xù)刪除32219中的哪個數(shù)字辕羽,132219始終小于14xxxx炭菌;所以刪除4為最優(yōu)策略。因為刪除了數(shù)字4逛漫,所以此時的k = k - 1 = 2黑低;
  3. 考慮第三位數(shù)字3,分為兩種可能:
    刪除3:1(3)2219 :刪除3的話我們可以得到12219酌毡;
    不刪除3:13(2219):不刪除4的話我們需要在2219中刪除一個數(shù)字克握;
    不難看出,無論后續(xù)刪除2219中的哪個數(shù)字枷踏,12219始終小于13xxx菩暗;所以刪除3為最優(yōu)策略。因為刪除了數(shù)字3旭蠕,所以此時的k = k - 1 = 1停团;
  4. 考慮第四位數(shù)字2旷坦,分為兩種可能:
    刪除2:1(2)219 :刪除2的話我們可以得到1219;
    不刪除2:12(219):不刪除2的話我們需要在219中刪除一個數(shù)字佑稠;
    發(fā)現(xiàn)我們沒辦法判斷12xx和1219誰比較大秒梅;所以暫時保留2等待后續(xù)的判斷為最優(yōu)策略;
  5. 考慮第五位數(shù)字2舌胶,分為兩種可能:
    刪除2:12(2)19 :刪除2的話我們可以得到1219捆蜀;
    不刪除2:122(19):不刪除2的話我們需要在19中刪除一個數(shù)字;
    不難看出幔嫂,無論后續(xù)刪除19中的哪個數(shù)字辆它,1219始終小于122x;所以刪除2為最優(yōu)策略履恩。因為刪除了數(shù)字3锰茉,所以此時k = k - 1 = 0
    截止到這里切心,我們成功的刪除了3個數(shù)字洞辣,所以最后輸出結(jié)果1219。
    那么如果k=4的時候呢昙衅?
    前五步依然一樣,我們得到了1219定鸟,而此時的k=1而涉;我們需要再刪除一個數(shù);
    可能看到上面的分析過程我們會慣性的認(rèn)為联予,接下來啼县,我們應(yīng)該考慮第六位數(shù)字1,因為保留1的時候121<129沸久,所以保留1季眷,刪除9,最后輸出121卷胯;
    其實不然子刮,正確的答案明顯是119,第六步直接考慮第六位是錯誤的窑睁!
    我們忽略了我們要取最優(yōu)策略挺峡,應(yīng)該盡可能的讓最高位取最小值,次高位取第二小的值担钮,直到k=0橱赠;所以正確的第六步應(yīng)該是在刪除了第五位數(shù)字2以后,考慮第四位的2是否應(yīng)該刪除箫津;
    所以進(jìn)展到1219狭姨,k=1時宰啦,我們給出正確的第六步比較:
  6. 考慮第四位數(shù)字2(以保留的數(shù)字中最后一位),分為兩種可能:
    刪除2:1(2)19 :刪除2的話我們可以得到119饼拍;
    不刪除2:12(19):不刪除2的話我們需要在19中刪除一個數(shù)字赡模;
    不難看出,無論后續(xù)刪除19中的哪個數(shù)字惕耕,119始終小于12x纺裁;所以刪除2為最優(yōu)策略。因為刪除了數(shù)字2司澎,所以此時k = k - 1 = 0欺缘;
    如何用程序來實現(xiàn)這個過程呢?
    上述的分析挤安,我們發(fā)現(xiàn)谚殊,如果我們創(chuàng)建一個數(shù)組專門用來存儲要保留的數(shù)字;為了保證保留的數(shù)的最高位是最小的蛤铜,次高位第二小...我們需要保證數(shù)組中的數(shù)以遞增的方式存儲嫩絮;
    當(dāng)前的數(shù)字則需要對數(shù)組中的數(shù)由高到低依次比較,只要當(dāng)前的數(shù)字小于數(shù)組中最后的數(shù)字围肥,我們就將數(shù)組中最后的數(shù)字刪除(k-1)剿干;
    然后再拿當(dāng)前的數(shù)字和新的數(shù)組中的數(shù)字進(jìn)行比較,直到k=0或者當(dāng)前的數(shù)字大于數(shù)組中最后的數(shù)字時穆刻,保留當(dāng)前的數(shù)字置尔;
    因為這個數(shù)組的元素滿足遞增順序所以在和當(dāng)前數(shù)字比較的時候,相當(dāng)于先進(jìn)后比較氢伟;滿足棧的數(shù)據(jù)結(jié)構(gòu)榜轿,所以我們用棧來模擬下存儲的過程:
    image.png

    image.png

    如果操作結(jié)束以后k>0或者數(shù)字0是最高位的時候呢?
    image.png
  7. 結(jié)束以后k>0:取前 stack.size() - k 個數(shù)字即可朵锣;
  8. 者數(shù)字0是最高位:棧為空時谬盐,遇見數(shù)字0,不把0壓入棧即可~诚些;
    最后我們給出代碼實現(xiàn)飞傀,這里我們用vector容器來代替stack存儲保留的數(shù)字;因為vector容器可以遍歷诬烹,更方便一些助析;

My Solution(C/C++完整實現(xiàn)):

#include <cstdio>
#include <iostream>
#include <string>  // 標(biāo)準(zhǔn)c++庫,cout重載的是string類庫的string類型椅您;不是cstring或string.h外冀,后者是C語言里面關(guān)于字符數(shù)組的函數(shù)定義的頭文件;
#include <vector>

using namespace std;

class Solution {
public:
    string removeKdigits(string num, int k) {
        string result = "";
        vector<int> mems;
        for (int i = 0; i < num.length(); i++) {
            int mem = num[i] - '0';
            if (k != 0) {
                while (!mems.empty() && mem < mems[mems.size() - 1]) {
                    mems.pop_back();
                    k -= 1;
                    if (k == 0) {
                        break;
                    }
                }
                if (!mems.empty() || mem != 0) {
                    mems.push_back(mem);
                }
            }
            else {
                mems.push_back(mem);
            }
        }
        int len = mems.size();
        if (k != 0) {
            len = len - k;
        }
        for (int i = 0; i < len; i++) {
            result.append(1, mems[i] + '0');  //在result后面添加一個字符掀泳;
        }
        if (result == "") {
            return "0";  //注意返回值類型為string雪隧,不能return 0或者return '0'西轩;
        }
        return result;
    }
};

int main() {
    Solution s;
    cout << s.removeKdigits("1432219", 4);
    getchar();
    return 0;
}

結(jié)果:

119`

My Solution(Python):

class Solution:
    def removeKdigits(self, num, k):
        """
        :type num: str
        :type k: int
        :rtype: str
        """
        tem_stack = []
        nums = list(num)
        # if len(nums) == k:
        #     return '0'
        # if len(nums) == 1:
        #     return num
        for i in range(len(nums)):
            if tem_stack == []:
                tem_stack.append(nums[i])
            elif nums[i] >= tem_stack[-1]:
                tem_stack.append(nums[i])
            while nums[i] < tem_stack[-1]:
                tem_stack.pop()
                k -= 1
                if k == 0:
                    tem_stack.append(nums[i])
                    break
                if tem_stack == [] or nums[i] >= tem_stack[-1]:
                    tem_stack.append(nums[i])
            if k == 0:
                tem_stack += nums[i+1:]
                break
        # for j in range(len(tem_stack)):
        #     if tem_stack[j] != '0':
        return ''.join(tem_stack[ :len(tem_stack) - k]).lstrip('0') or '0'

Reference:

class Solution:
    def removeKdigits(self, num, k):
        """
        :type num: str
        :type k: int
        :rtype: str
        """
        out=[]
        for digit in num:
            while k and out and out[-1] > digit:
                out.pop()
                k-=1
            out.append(digit)
        return ''.join(out[:-k or None]).lstrip('0') or "0"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脑沿,隨后出現(xiàn)的幾起案子藕畔,更是在濱河造成了極大的恐慌,老刑警劉巖庄拇,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件注服,死亡現(xiàn)場離奇詭異,居然都是意外死亡措近,警方通過查閱死者的電腦和手機溶弟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞭郑,“玉大人辜御,你說我怎么就攤上這事∏牛” “怎么了擒权?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阁谆。 經(jīng)常有香客問我碳抄,道長,這世上最難降的妖魔是什么场绿? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任剖效,我火速辦了婚禮,結(jié)果婚禮上裳凸,老公的妹妹穿的比我還像新娘。我一直安慰自己劝贸,他們只是感情好姨谷,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著映九,像睡著了一般梦湘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上件甥,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天捌议,我揣著相機與錄音,去河邊找鬼引有。 笑死瓣颅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的譬正。 我是一名探鬼主播宫补,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼檬姥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粉怕?” 一聲冷哼從身側(cè)響起健民,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贫贝,沒想到半個月后秉犹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡稚晚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年崇堵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜈彼。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡筑辨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幸逆,到底是詐尸還是另有隱情棍辕,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布还绘,位于F島的核電站楚昭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拍顷。R本人自食惡果不足惜抚太,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昔案。 院中可真熱鬧尿贫,春花似錦、人聲如沸踏揣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捞稿。三九已至又谋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娱局,已是汗流浹背彰亥。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衰齐,地道東北人任斋。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像耻涛,于是被迫代替她去往敵國和親仁卷。 傳聞我的和親對象是個殘疾皇子穴翩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 青春是匹不羈的野馬 午夜在山路上奔馳 月亮跟隨著我瘋狂 你是否也在注視 這一輪明月 告訴我 一定會在見 等待的容顏...
    燃燒吧情懷閱讀 234評論 0 7
  • 今天下午老師教我們折紙了,我們折了個小花貓锦积,我說這個綠色的小花貓芒帕,我做得非常好,有的小朋友還不會折小花貓丰介,老師教了...
    王文哲同學(xué)閱讀 74評論 0 0
  • 曾經(jīng)很不認(rèn)可中國畫的清淡背蟆,覺得寥寥幾筆畫出的東西沒有深度。隨著時間的推移哮幢,卻漸漸感受到了水墨里的云淡風(fēng)輕带膀,技法里的...
    沫師師閱讀 807評論 9 17