LeetCode 402. Remove K Digits

本文详细解析了LeetCode402题“Remove K Digits”的解题思路及算法实现,介绍了如何通过使用单调栈或双端队列来解决数字串中移除指定数量数字以得到最小可能数值的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[Med] LeetCode 402. Remove K Digits

链接: https://leetcode.com/problems/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.

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:

num = “1234567890”
k = 9
-> 0

Note:

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

Tag: Pre-Sum
解题思路
这道题目让我们在一个数字中拿掉某几个,使得剩余的数字值最小。同时注意边界条件,比如说
不能有Leading zero, 如果k > 数字长度的话怎么处理。 我们可以用stack或者dequeue来做,这里我用的是dequeue, 因为这样可以比较容易的访问dequeue的头部,以便把leading zero去掉。
这题跟 LeetCode 上之前那道 Create Maximum Number 有些类似,可以借鉴其中的思路,
如果n是 num 的长度,我们要去除k个,那么需要剩下 n-k 个,怎么判断哪些数字应该去掉呢?
首先来考虑,若数字是递增的话,比如 1234,那么肯定是要从最后面移除最大的数字。若是乱序
的时候,比如 1324,若只移除一个数字,移除谁呢?我们一眼可以看出是移除3,变成 124 是最小。但是怎么设计算法呢,实际上这里利用到了单调栈的思想,这里我们维护一个递增栈,只要发现当前的数字小于栈顶元素的话,就将栈顶元素移除,比如点那个遍历到2的时候,栈里面有1和3,此时2小于栈顶元素3,那么将3移除即可。为何一定要移除栈顶元素呢,后面说不定有更大的数字呢?这是因为此时栈顶元素在高位上,就算后面的数字再大,也是在低位上,我们只有将高位上的数字尽可能的变小,才能使整个剩下的数字尽可能的小。我们开始遍历给定数字 num 的每一位,对于当前遍历到的数字c,进行如下 while 循环,如果 dq 不为空,且k大于0,且 dq 的顶部大于c,那么应该将 res 的顶部移去,且k自减1。当跳出 while 循环后,我们将c加入 res 中,最后将 res 的大小重设为 n-k。根据题目中的描述,可能会出现 “0200” 这样不符合要求的情况,所以我们用一个 while 循环来去掉前面的所有0,然后返回时判断是否为空,为空则返回 “0”:

TIME & SPACE : O(N)
解法一:

class Solution {
    public String removeKdigits(String num, int k) {
        if(k>=num.length()) return "0";
        Deque<Integer> dq = new LinkedList();
        for(int i=0; i<num.length(); i++){
            int c = num.charAt(i)-'0';
            while(!dq.isEmpty() && k>0  && dq.peekLast() > c){
                k--;
                dq.removeLast();
            }
            dq.addLast(c);
        }
        
        StringBuffer sb = new StringBuffer();
        
        //remove the leading zero
        while(!dq.isEmpty() && dq.peekFirst() ==0){
            dq.pollFirst();
        }
        
        //add the element from dequeue to final result
        //we need to remove k element, then we just add dq.size() -k element to our result
        while(!dq.isEmpty() && dq.size()>k){
            sb.append(dq.pollFirst());
        } 
        
        //if the dequeue becomes empty, then return 0, else return string
        return sb.length()!=0? sb.toString(): "0";
    }
}

解法二:

class Solution {
    public String removeKdigits(String num, int k) {
        if(num.length() <=k) return "0";
        Stack<Integer> s = new Stack<>();
        
        for(int i=0; i <num.length(); i++){
            char c = num.charAt(i);
            while(k > 0 && !s.isEmpty() && num.charAt(s.peek()) > c){
                s.pop();
                k--;
            }
            s.push(i);
        }
        
 
      
        StringBuffer sb = new StringBuffer();
        while(!s.isEmpty()){
            if(k-- >0) s.pop();
            else sb.append(num.charAt(s.pop()));    
        } 
        sb.reverse();
        while(sb.length()>0){
            if(sb.charAt(0) != '0') break;
            else sb.deleteCharAt(0);
        }
        
        return sb.length() == 0? "0" :sb.toString();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值