【LeetCode每日一题】单调栈 402 移掉k位数字

402. 移掉 K 位数字

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k **位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

如果有 m+1 位数字,S1

a 0 a 1 a 2 . . . . a m a_0a_1a_2....a_m a0a1a2....am

需要去掉n位数字,S2

a i , a k , , , , a n a_i,a_k,,,,a_n ai,ak,,,,an

剩余的 m+1-n 位。S3

假如用去掉的 n 位数字中的一个数字

a i ( a i < a j ) a_i (a_i < a_j) aiai<aj

替换剩余的 S3 里面的最大的字符 (a_j), 那么 新的数字会比原来的S3 要小,因此,我们用来去掉的n位数字中的每一个数字都需要大于剩余的数字

⇒ 去掉前N个最大的数字。

⇒ 通过单调栈去掉极大值,尖峰。

经过上面的分析,我们基本可以确定需要使用栈来充当这个容器了。当遍历每一个数字的时候,如果当前数字比栈顶数字大,是递增,那么就可以直接入栈,因为下一个数字有可能比当前的大;如果当前数字比栈顶的小,那么就需要将栈顶的元素弹出删除,因为这个栈顶元素既是递增的最后一个数字,也是递减的第一个数字,是一个尖峰,再删除过程中记录删除的个数或者将k - 1,当删除了所有k个数字后,就得出了结果。

遍历完毕后,k个数字没有移除完,比如数字123456789,移除3个数字,按照上面的分析,得出的结果还是123456789,出现这种情况是因为移除部分数字后,得出的结果是一个高位递增的数,所以无法再移除了,这个时候,只要出现这种情况,将低位的数字移除掉剩余个数即可,可以仔细想想这一个特殊点

var removeKdigits = function(num, k) {

    if(k === num.length){
        return "0";
    }

    let stack = [];
    for(let i = 0; i < num.length; i++){
        // 遇到尖峰,去掉尖峰  || 单调递减
        while(k && stack.length && stack.at(-1) > num[i]){
            stack.pop();
            k--;
        }
        // 维护的是一个递增的栈,但是首位不能是0
        if(!(nums[i]==="0" && stack.length === 0)){
            stack.push(num[i]);
        }
    }

// 移除尖峰,如果没有尖峰,就把低位的删除即可 ||单调递增
    while(k>0 && stack.length){
        stack.pop();
        k--;
    }

    return stack.length === 0 ? "0" : stack.join("");

};
  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凭栏听雨客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值