LeetCode第 402 题:移掉K个数字(C++)

402. 移掉K位数字 - 力扣(LeetCode)

主要思路;由最高位开始,比较低一位数字,如高位大,移除,若高位小,则向右移一位继续比较两个数字,直到高位大于低位则移除,循环k次。

多次遍历

但是这题的特殊情况比较难处理,可以暴力采取每次都从头遍历,但是复杂度会增加:

class Solution {
public:
    string removeKdigits(string num, int k) {
        if(num.size() == k) return "0";
        for(int i = 0; i < k; ++i){
            int j = 0;
            while(j < num.size()-1 && num[j] <= num[j+1])    ++j;
            if(j >= num.size()) num.erase(num.size()-1, 1);
            else num.erase(j, 1);
        }
        int beg = 0;
        while(num[beg] == '0')  ++beg;//取出前导0
        string res = num.substr(beg);
        return res == "" ? "0" : res;
    }
};

这样的效率一般,因为每次都从头遍历。

一次遍历

优化如下:

class Solution {
public:
    string removeKdigits(string num, int k) {
        if(num.size() == k) return "0";
        int j = 1, flag = 1;
        for(int i = 0; i < k; ++i){
            if(flag == 1){
                while(j < num.size() && num[j-1] <= num[j])    ++j;
                num.erase(j-1, 1);
                if(j > 1) --j;//因为删除了一个嘛,退回去让j指向之前指向的元素
                if(j == num.size()) flag = -1;//走到了最后,那么后续就只能从末尾依次删除了
            }else   num.erase(num.size()-1, 1);
        }
        int beg = 0;
        while(num[beg] == '0')  ++beg;//取出前导0
        string res = num.substr(beg);
        return res == "" ? "0" : res;
    }
};

单调栈

不过上述代码还是不够快,因为删除操作还是比较耗时的。还可以借助栈操作,参考
移掉K位数字 - 移掉K位数字 - 力扣(LeetCode)

class Solution {
public:
    string removeKdigits(string num, int k) {
        stack<char> s;
        for(int i = 0; i < num.size(); ++i){
            while(!s.empty() && num[i] < s.top() && k != 0){//注意这儿是while循环
                s.pop();
                --k;
            }
            if(s.empty() && num[i] == '0')  continue;//跳过前导0
            s.push(num[i]);
        }
        string res;
        while(!s.empty()){
            if(k > 0) --k;//移除未结束,从栈顶依次移除
            else if(k == 0) res += s.top();//移除结束,生成结果串
            s.pop();
        }
        reverse(res.begin(), res.end());
        return res == "" ? "0" : res;
    }
};

不用栈,直接用字符串操作,一样的思路:

class Solution {
public:
    string removeKdigits(string num, int k) {
        string res;
        for(int i = 0; i < num.size(); ++i){
            while(!res.empty() && num[i] < res.back() && k != 0){//注意这儿是while循环
                res.pop_back();
                --k;
            }
            if(res.empty() && num[i] == '0')  continue;//跳过前导0
            res += num[i];
        }
        while(k > 0 && !res.empty()){
            res.pop_back();
            --k;
        }
        return res == "" ? "0" : res;
    }
};

其实这个思路和一次遍历的那个,本质上差不多,不过那个删除操作比较耗时。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值