从大到小仅需这几步!

Python实战社群

Java实战社群

长按识别下方二维码,按需求添加

扫码关注添加客服

进Python社群▲

扫码关注添加客服

进Java社群

作者丨袁厨

来源丨袁厨的算法小屋

移除K位数字

今天给大家带来一个栈的中等题目,移掉K位数字,题目很简单,但是很有趣。另外明天继续给大家带来一道栈和队列题目(困难),那么咱们的栈和队列模块就结束啦,下周开始整字符串的题目啦!

题目描述

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意:

num 的长度小于 10002 且 ≥ k。num 不会包含任何前导零。

示例 1 :

输入: num = "1432219", k = 3 

输出: "1219" 

解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。

示例 2 :

输入: num = "10200", k = 1 

输出: "200" 

解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入: num = "10", k = 2 

输出: "0" 

解释: 从原数字移除所有的数字,剩余为空就是0

题目很容易理解,而且也很容易实现,因为在示例中几乎把所有特殊情况都进行了举例,我们直接代码实现就好啦。

下面我们来看一下用栈的解题思路,因为我们需要删除掉K位数字得到最小值,那么我们需要注意的是,删除的数字应该尽量在高位,则当前位小于前一位时,对前一位出栈,当前位入栈。大家思考一下思路是不是这样呢?

另外我们需要注意的是,仅删除K位数字,得到最小值,比如54321,我们删除3位,得到21。但是刚才我们说当前位小于前一位时,则前一位出栈,当前位入栈,如果继续执行的话2也会被移除,所以我们还需要加上删除K位的规则。

废话不多说我们直接上动图,把该题吃透!

移除K位数字

PPT文字

这里需要注意的是,我们不需要将0入栈,因为0如果处于栈底,没有比它更小的值所以它不会被移除,我们只有在最后才有机会处理它。因为我们的010 = 10 ,首位0是需要在最后去掉的。所以我们这里可以直接不让其入栈,continue掉这次循环,也不改变K值,这样我们最后出栈处理时就不用考虑啦。这样逻辑就比官方题解好理解一些,也简洁一些。

这里需要注意的是,我们的K值还为2,我们目前仅删除2位数字,但是我们需要删除4位,但是后面的几位都是当前位大于前一位。所以我们需要在遍历结束后再移除后面最大的两位数字

class Solution {
    public String removeKdigits(String num, int k) {
    
        //特殊情况全部删除
        if(num.length() == k){
            return "0";
        }
        char[] s = num.toCharArray();
        Stack<Character> stack = new Stack<>();
        
        //遍历数组
        for(Character i : s){
        
          //移除元素的情况,k--
            while(!stack.isEmpty() && i < stack.peek() && k > 0){
                   stack.pop();
                   k--;
            }
            
            //栈为空,且当前位为0时,我们不需要将其入栈
            if(stack.isEmpty() && i == '0'){
                continue;
            }
            
            stack.push(i);
        }
        while(k > 0){
        
            stack.pop();
            
            k--;
        }
        //这个是最后栈为空时,删除一位,比如我们的10,删除一位为0,按上面逻辑我们会返回"",所以我们让其返回"0"
         if(stack.isEmpty()){
             return "0";
         }
         
         //反转并返回字符串
         
         StringBuilder str = new StringBuilder();
         while(!stack.isEmpty()){
             str.append(stack.pop());
         }
         return str.reverse().toString();
    }
}

这个题目也是很不错的,题目是精心挑选的,然后动图里面的例子也是精心构思过的。所以大家记得打卡呀!希望可以帮助到你。我以后每天会在文章下面放一个读者讨论(目前还没有留言功能),大家阅读完文章消化过之后可以在下面打卡,这样也算是给自己一个总结。另外我以后还会在文章下面放一个面试逻辑题,以备不时之需,大家也可以对逻辑题进行讨论。

逻辑题:五个大小相同的一元硬币,要求两两接触,应该怎么摆?

程序员专栏 扫码关注填加客服 长按识别下方二维码进群

近期精彩内容推荐:  

 几句话,离职了

 中国男性的私密数据大赏,女生勿入!

 为什么很多人用“ji32k7au4a83”作密码?

 一个月薪 12000 的北京程序员的真实生活 !


在看点这里好文分享给更多人↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值