LeetCode 402 Remove K Digits 题解

题意简述:给定一个有数字组成的字符串,要求从里面删去k个数字后剩下的数尽可能小,求最小值。
输入:一个数字组成的字符串num,要删去的数量k
输出:所得到的数的最小值
示例:对于字符串“1432219”,要删去3个数,可以删去第2、3、4位,剩下的“1219”是最小的。


题解:
无论我们怎样操作,最终得出的数的位数是固定的(num的长度减去k),那么要让数尽可能小,就是要让高位的数字尽可能小。一个方法是,把数字小的位先找出了,然后按升序排列。但是这个方法忽略了一个问题:最后得出的数中那些数字的先后关系应该跟它们在原num字符串中一致。
为了保持这种先后关系,我们可以采取以下方法:

  • 使用一个字符串res存放结果
  • 从左到右遍历num,将当前的数字向后插入到res中,在此之前先把res中比这个数字大的数字从后到前依次弹出,每弹出一次记录一次,弹出的次数不能超过k次。这样就可以保证,得到的那一位数字肯定是最小值(因为之前占据着那一位的数字比它大,而且已经弹出,除非弹出次数已够)。

需要注意的细节:

  • 有可能在原字符串中升序排列的情况比较多,导致弹出的次数不足k次,这时就取res的前(num的长度-k)位。
  • 最后需要除去res的leading zero。

代码实现如下,该算法的时间复杂度是O(N+k)(遍历一次num,做k次弹出),空间复杂度是O(N)(存放结果的res)。

class Solution {
public:
    string removeKdigits(string num, int k) {
        string res;
        auto keep = num.size() - k;

        for(auto ch: num) {
            while(k > 0 && res.size() > 0 && res.back() > ch) {
                res.pop_back();
                k--;
            }
            res.push_back(ch);
        }

        res = res.substr(0, keep);
        auto it = res.find_first_not_of("0");
        if (it != string::npos)  res = res.substr(it);
        else if(res.back() == '0') return "0";

        if(res.size() == 0) return "0";
        else return res;    
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值