Leetcode 402. 移掉K位数字

Leetcode 402. 移掉K位数字

贪心;单调栈

类型题:

解题思路:

核心:

从头到尾遍历,若当前字符cur小于前面的字符,则淘汰前面大的字符。因为若cur前面存在一个比cur还要大的字符,则构成的数字不会是最小。

实现:

维护一个单调栈,每次当前字符cur都跟栈顶K比较,若栈顶元素大于cur,则出栈,直到不满足栈顶元素>cur(这就是一个while循环)。 最终从栈底得到每一个字符,并构成答案。即对于每个数字,如果该数字小于栈顶元素,我们就不断地弹出栈顶元素,直到

  • 栈为空
  • 或者新的栈顶元素不大于当前数字
  • 或者我们已经删除了k个数字

细节:

  • 每删除一个栈顶元素,k要减1,若当前已经删除了k个了(k==0),不用比较了,cur直接进栈。即要满足k>0,才能从栈顶删除元素。
  • 可能原字符串是升序的,例如123456,K=1,栈中元素为123456,很明显不能将栈中所有字符都返回,所以定义remain为最终留下的字符个数,即栈中一定有remain个字符
  • 可能会有前导0,在得到结果前要先删除前导0,从栈底删除,使用双端队列Deque方便操作。
class Solution {
    public String removeKdigits(String num, int k) {
        int length = num.length();
        int remain = length - k;//保留remain个字符
        Deque<Character> stack = new LinkedList<>();
        for (int i = 0; i < length; ++i) {
            char cur = num.charAt(i);
            while (!stack.isEmpty() && stack.peekLast() > cur && k > 0) {
                stack.pollLast();
                k--;
            }
            stack.offerLast(cur);
        }
        while (stack.size() > remain) {
            stack.pollLast();
        }
        while (!stack.isEmpty() && stack.peekFirst() == '0') {
            stack.pollFirst();
        }
        StringBuilder ans = new StringBuilder();
        for (char c : stack) {
            ans.append(c);
        }
        return ans.length() == 0 ? "0" : ans.toString();
    }
}

复杂度分析:

时间复杂度: O(n)。

空间复杂度: O(n)。栈存储数字的空间。

参考文章

https://leetcode-cn.com/problems/remove-k-digits/solution/yi-zhao-chi-bian-li-kou-si-dao-ti-ma-ma-zai-ye-b-5/

https://leetcode-cn.com/problems/remove-k-digits/solution/yi-diao-kwei-shu-zi-by-leetcode-solution/

上一篇:【图像处理】基于matlab鼠标画图【含Matlab源码 402期】


下一篇:从0开始学算法--排序(1.9基数排序)