移掉 K 位数字

移掉 K 位数字

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

解题思路

首先我们要了解一个关于数学的前置知识,对于两个相同长度的数字序列,最左边不同的数字决定了这两个数字的大小,例如,对于 A = 1axxxA = 1axxx,B = 1bxxxB = 1bxxx,如果 a > b,则 A > B

基于此,我们可以知道,若要使得剩下的数字最小,需要保证靠前的数字尽可能小

如果使用暴力法,那思路就是:

  • 从左到右遍历
  • 对于每一个遍历到的元素,前一个元素比当前元素大,则丢弃前一个元素,否则保留前一个元素

需要注意的是,如果给定的数字是一个单调递增的数字,那么我们的算法会永远选择不丢弃。这个题目中要求的,我们要永远确保丢弃 k 个数字,因此思路还应该稍加修改:

  • 每次丢弃一次,k 减去 1。当 k 减到 0 ,我们可以提前终止遍历
  • 而当遍历完成,如果 k 仍然大于 0。不妨假设最终还剩下 x 个需要丢弃,那么我们需要选择删除末尾 x 个元素

然而暴力的实现复杂度最差会达到 O(nk)(考虑整个数字序列是单调不降的),因此我们需要加速这个过程

可以用一个栈维护当前的答案序列,栈中的元素代表截止到当前位置,删除不超过 k 次个数字时,所能得到的最小整数。根据之前的讨论:在使用 k 个删除次数之前,栈中的序列从栈底到栈顶单调不降。因此,对于每个数字,如果该数字小于栈顶元素,我们就不断地弹出栈顶元素,直到

  • 栈为空
  • 新的栈顶元素不大于当前数字
  • 已经删除了 k 位数字

上述步骤结束后我们还需要针对一些情况做额外的处理:

  • 如果我们删除了 m 个数字且 m<k,我们需要从序列尾部删除额外的 k-m 个数字
  • 如果最终的数字序列存在前导零,我们要删去前导零
  • 如果最终数字序列为空,我们应该返回 0
class Solution {

    public String removeKdigits(String num, int k) {
        Deque<Character> deque = new LinkedList<>();
        for(int i = 0; i < num.length(); i++) {
            while(!deque.isEmpty() && k > 0 && deque.peekLast() > num.charAt(i)) {
                deque.pollLast();
                k--;
            }
            deque.offerLast(num.charAt(i));
        }
        for(int i = 0; i < k; i++) {
            deque.pollLast();
        }
        StringBuilder str = new StringBuilder();
        boolean leadingZero = true;
        while(!deque.isEmpty()) {
            char digist = deque.pollFirst();
            if(leadingZero && digist == '0') {
                continue;
            }
            leadingZero = false;
            str.append(digist);
        }
        return str.length() == 0 ? "0" : str.toString();
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/2599.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • IE浏览器安装插件(ocx)提示“windows 已经发现此文件有一个问题”怎么办?「建议收藏」

    IE浏览器安装插件(ocx)提示“windows 已经发现此文件有一个问题”怎么办?「建议收藏」当我们在win7操作系统中浏览网页,在有些网页需要登入账号密码需要安装插件才能够输入进去。一般我们只需按步骤下载安装插件就可以了。但是由用户反映,在下载好插件准备运行的时候,发现怎么样都安装不了,这样就无法登入账号了,该怎么办呢?接下来小编给大家介绍下解决方法。步骤:1、打开IE浏览器,在浏览器中点一下“alt”键,然后点击“工具”—“internet选项”;2、在

    2022年7月14日
    82
  • Java8-Stream API

    Java8-Stream API

    2022年3月7日
    36
  • 正则表达式匹配任意字符(包括换行符)[通俗易懂]

    正则表达式匹配任意字符(包括换行符)[通俗易懂]可以用([\s\S]*),也可以用“([\d\D]*)”、“([\w\W]*)”来匹配,就可以匹配包括换行符在内的任意字符。http://tools.jb51.net/regex/javas

    2022年7月1日
    33
  • ENVI5.3.1使用Landsat 8影像进行辐射定标和大气校正实例操作

    ENVI5.3.1使用Landsat 8影像进行辐射定标和大气校正实例操作ENVI5.3.1使用Landsat8影像进行辐射定标和大气校正实例操作

    2022年7月23日
    9
  • pip安装scrapy失败_scrapy框架运行

    pip安装scrapy失败_scrapy框架运行错误如图所示,running setup.py install for Twisted…..errorTwisted依赖库安装报错,重新下载手动安装一下下载网址:https://www.lfd.uci.edu/~gohlke/pythonlibs注意:看下安装的python是什么版本,我安装的python 3.9.0,就下载cp39,64位的下载安装的版本不对,就会报:Twisted-20.3.0-cp38-cp38-win_amd64.whl is not a support…

    2022年8月18日
    8
  • java实现编译器_实现一个简单的编译器

    java实现编译器_实现一个简单的编译器简单的说编译器就是语言翻译器,它一般将高级语言翻译成更低级的语言,如GCC可将C/C++语言翻译成可执行机器语言,Java编译器可以将Java源代码翻译成Java虚拟机可以执行的字节码。编译器如此神奇,那么它到底是如何工作的呢?本文将简单介绍编译器的原理,并实现一个简单的编译器,使它能编译我们自定义语法格式的源代码。(文中使用的源码都已上传至GitHub以方便查看)。自定…

    2022年7月7日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号