力扣-402.移掉K位数字

90 阅读1分钟

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

示例 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次数没用完,则从队列尾端删除k个数字(因为后面进的比前面大,所有从后删除)
  • 最后使用拼接字符串保存结构,并删除所有前置0
public static String removeKdigits(String num, int k) {
        int len = num.length();
        if (len <= k)
            return "0";
        char[] chars = num.toCharArray();
        Deque<Character> deque = new LinkedList<Character>();
        //优先队列,此处代替栈使用,可以简化掉字符串反转这一操作。
        StringBuilder builder = new StringBuilder();
        int i = 0;
        while (i != len){
            while (!deque.isEmpty() && chars[i] < deque.peekLast() && k != 0){
                deque.pollLast();
                k--;
            }
            deque.offerLast(chars[i++]);
        }
        for (int j = 0; j < k; ++j) {
            deque.pollLast();
        }
        while (!deque.isEmpty()){
            builder.append(deque.pollFirst());
        }
        while (builder.charAt(0) == '0' && builder.length() > 1)
            builder.deleteCharAt(0);
        return builder.toString();
    }