漫画:删去k个数字后的最小值

转载自  漫画:删去k个数字后的最小值

 

 

我们来举一个栗子:

给定整数 541270936,要求删去一个数,让剩下的整数尽可能小。

此时,无论删除哪一个数字,最后的结果都是从9位整数变成8位整数。既然同样是8位整数,我们显然应该优先把高位的数字降低,这样对新整数的值影响最大。

 

如何把高位的数字降低呢?很简单,我们把原整数的所有数字从左到右进行比较,如果发现某一位的数字大于它右面的数字,那么在删除该数字后,必然会使得该数位的值降低,因为右面比它小的数字顶替了它的位置。

在咱们这个例子中,数字5右侧的数字4小于5,所以删除数字5,最高位数字降低成了4。

 

 

 

 

 

 

 

 

 

 

/*** 删除整数的k个数字,获得删除后的最小值* @param num  原整数* @param k  删除数量*/public static String removeKDigits(String num, int k) {String numNew = num;for(int i=0; i<k; i++){boolean hasCut = false;//从左向右遍历,找到比自己右侧数字大的数字并删除for(int j=0; j<numNew.length()-1;j++){if(numNew.charAt(j) > numNew.charAt(j+1)){numNew = numNew.substring(0, j) + numNew.substring(j+1,numNew.length());hasCut = true;break;}}//如果没有找到要删除的数字,则删除最后一个数字if(!hasCut){numNew = numNew.substring(0, numNew.length()-1);}//清除整数左侧的数字0numNew = removeZero(numNew);}//如果整数的所有数字都被删除了,直接返回0if(numNew.length() == 0){return "0";}return numNew;}private static String removeZero(String num){for(int i=0; i<num.length()-1; i++){if(num.charAt(0) != '0'){break;}num = num.substring(1, num.length()) ;}return num;}public static void main(String[] args) {System.out.println(removeKDigits("1593212",3));System.out.println(removeKDigits("30200",1));System.out.println(removeKDigits("10",2));System.out.println(removeKDigits("541270936",3));}

小灰的代码使用了两层循环,外层循环基于删除次数(k),内层循环从左到右遍历所有数字。

当遍历到需要删除的数字时,利用字符串的自身方法subString() 把对应数字删除,并重新拼接字符串。

显然,这段代码的时间复杂度是O(kn)。

 

结果,提交以后......

 

翻译过来就是:恭喜你,打败了16.56%的小伙伴!

 

 

1.每一次内层循环,都需要从头遍历所有数字

比如给定的整数是 11111111111114132,我们在第一轮循环中,需要遍历大部分数字,一直遍历到数字4,发现4>1,从而删除4。

以目前的代码逻辑,下一轮循环中,我们要从头开始遍历,再次重复遍历大部分数字,一直遍历到数字3,发现3>2,从而删除3。

事实上,我们应该停留在上一次删除的位置继续进行比较。而不是从头开始。

2.subString方法本身性能不高

subString方法的底层实现,涉及到了新字符串的创建,以及逐个字符的拷贝。这个方法自身的时间复杂度是O(n)。

因此,我们应该避免在每删除以后数字后就调用subString方法。

 

 

 

/*** 删除整数的k个数字,获得删除后的最小值* @param num  原整数* @param k  删除数量*/public static String removeKDigits(String num, int k) {//新整数的最终长度 = 原整数长度 - kint newLength = num.length() - k;//创建一个栈,用于接收所有的数字char[] stack = new char[num.length()];int top = 0;for (int i = 0; i < num.length(); ++i) {//遍历当前数字char c = num.charAt(i);//当栈顶数字大于遍历到的当前数字,栈顶数字出栈(相当于删除数字)while (top > 0 && stack[top-1] > c && k > 0) {top -= 1;k -= 1;}//遍历到的当前数字入栈stack[top++] = c;}// 找到栈中第一个非零数字的位置,以此构建新的整数字符串int offset = 0;while (offset < newLength && stack[offset] == '0') {offset++;}return offset == newLength? "0": new String(stack, offset, newLength - offset);}public static void main(String[] args) {System.out.println(removeKDigits("1593212",3));System.out.println(removeKDigits("30200",1));System.out.println(removeKDigits("10",2));System.out.println(removeKDigits("541270936",3));}

代码中非常巧妙地运用了栈的特性,在遍历原整数的数字时,让所有数字一个个入栈,当某个数字需要删除时,让该数字出栈。最后,程序把栈中的元素转化为字符串结果。

我们仍然以整数 541270936,k=3 为例:

遍历到数字5,数字5入栈:

 

遍历到数字4,发现栈顶5>4,栈顶5出栈,数字4入栈:

 

遍历到数字1,发现栈顶4>1,栈顶4出栈,数字1入栈:

 

继续遍历数字2,数字7,依次入栈。

 

遍历数字0,发现栈顶7>0,栈顶7出栈,数字0入栈:

 

此时k的次数已经用完,无需再比较,剩下的数字一口气入栈:

 

此时栈中的元素就是最终的结果。

代码只对所有数字遍历了一趟,遍历的时间复杂度是O(n),而后把栈转化为字符串的时间复杂度也是O(n),所以最终的时间复杂度是O(n)

同时,程序中利用栈来回溯遍历过的数字以及删除数字,所以程序的空间复杂度是O(n)

 

 

 

 

leetcode原题链接如下,有兴趣的小伙伴可以自己尝试哦:

https://leetcode.com/problems/remove-k-digits/description/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 InSpec 实现符合性即代码

法规符合性是每个企业必须面对的一个现实问题。同时&#xff0c;随着改变业界格局的新技术以及客户对数字服务的期望的出现&#xff0c;竞争压力也随之增加。各行业能否在快速交付新产品和服务的同时&#xff0c;仍然履行法规符合性义务&#xff1f; 回答是肯定的。解决方案就是…

计算机专业毕业后能做什么工作?

众所周知&#xff0c;目前比较火的专业之一莫过于计算机专业了。在这个互联网时代&#xff0c;越来越多的人选择去学习计算机专业&#xff0c;可是你知道计算机专业毕业后都有哪些岗位可选择吗&#xff1f;各个岗位的工作任务主要是什么&#xff1f;以下是对于计算机专业中各个…

什么是 binlog

转载自 什么是 binlog 引言 为什么写这篇文章? 大家当年在学MySQL的时候&#xff0c;为了能够迅速就业&#xff0c;一般是学习一下MySQL的基本语法&#xff0c;差不多就出山找工作了。水平稍微好一点的童鞋呢还会懂一点存储过程的编写&#xff0c;又或者是懂一点索引的创建…

[信息安全] 4.一次性密码 amp;amp;amp;amp; 身份认证三要素

在信息安全领域&#xff0c;一般把Cryptography称为密码&#xff0c;而把Password称为口令。日常用户的认知中&#xff0c;以及我们开发人员沟通过程中&#xff0c;绝大多数被称作密码的东西其实都是Password&#xff08;口令&#xff09;&#xff0c;而不是真正意义上的密码。…

干货!sqlserver数据库所有知识点总结整理,含代码(挺全的)

01T-SQL案例整理已知有一个表&#xff1a;该表的字段有&#xff1a;id,name,date,gradeid,email&#xff0c;表名为table_name,按要求实现下面内容。1.插入一条记录&#xff1a;insert into table_name values (1,刘世豪,2017-10-21,1,666qq.com)2.将学号是1的学生姓名修改成张…

深入源码分析Java线程池的实现原理

转载自 深入源码分析Java线程池的实现原理 程序的运行&#xff0c;其本质上&#xff0c;是对系统资源&#xff08;CPU、内存、磁盘、网络等等&#xff09;的使用。如何高效的使用这些资源是我们编程优化演进的一个方向。今天说的线程池就是一种对CPU利用的优化手段。 网上有…

“桌面日历”记录的事件居然是看某某视频……

某年某月某下午&#xff0c;正在激情澎湃的在讲台上讲课&#xff0c;忽发现医学生缓缓的将右手举起来&#xff0c;见状&#xff0c;不用想&#xff0c;他一定有问题&#xff0c;嗯……要问我。于是&#xff0c;紧走几步下去&#xff0c;问他怎么了&#xff0c;他说他的某某功能…

开源个.NetCore写的 - 并发请求工具PressureTool

本篇和大家分享的是一个 并发请求工具&#xff0c;并发往往代表的就是压力&#xff0c;对于一些订单量比较多的公司这种情况很普遍&#xff0c;也因此出现了很多应对并发的解决方案如&#xff1a;分布式&#xff0c;队列&#xff0c;数据库锁等&#xff1b; 对于没有遇到过或者…

浅析DNS域名解析过程

转载自 浅析DNS域名解析过程 对于每一个HTTP请求发起过程中&#xff0c;都有很重要的一个步骤——DNS解析&#xff0c;本篇文章将跟着DNS解析过程来分析域名是如何解析的。 一、DNS域名解析步骤 下图是DNS域名解析的一个示例图&#xff0c;它涵盖了基本解析步骤和原理。 下…

最好的方法,是为你们量身定制!

昨天还和佟老师在讨论3班的学习情况&#xff0c;整体来说&#xff0c;学习氛围还是比较好的。由于近几天各种事纠结在一块儿&#xff0c;本来想给三班的学生制作一个提升计划&#xff0c;一直都腾不出来手。今天&#xff0c;终于抽了一点点时间&#xff0c;在原来互帮互助计划的…

Entity Framework Core 命名约定

注意&#xff1a;我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布时&#xff0c;功能可能存在变动。Entity Framework 迁移允许从模型生成数据库&#xff0c;这意味着必须从类名和属性名生成数据库对象的名称。对于大多数人来说使用默认名称是没有问…

ZOJ1654-Place the Robots【最大匹配,图论】

正题 大意 一个n*m个地方&#xff0c;有墙&#xff0c;草地和空地。在空地可以放机器人&#xff0c;机器人会将看到的其他机器人 [河蟹] 掉。他不能隔墙看。求最多能放多少个机器人。 解题思路 这里用一种奇特的构图方法&#xff0c; &#xff08;盗一下ppt里的图&#xff0…

彻底理解JVM常考题之分级引用模型

转载自 彻底理解JVM常考题之分级引用模型 本文通过探析Java中的引用模型&#xff0c;分析比较强引用、软引用、弱引用、虚引用的概念及使用场景&#xff0c;知其然且知其所以然&#xff0c;希望给大家在实际开发实践、学习开源项目提供参考。 Java的引用 对于Java中的垃圾…

越优秀的人越努力,越努力的人越幸运!

昨日晚间&#xff0c;学校值班&#xff0c;在楼道里面巡查几遍之后发现无异常情况&#xff0c;接着就去值班室中打开电脑忙自己的事。过了没一会儿&#xff0c;3班三学生去找我了&#xff0c;对我说&#xff0c;最近班里的学习情况不是太好&#xff0c;部分学生上课容易打盹&am…

SOA和微服务之间的区别

近几年&#xff0c;我们有很多文章对SOA和微服务之间的不同点和相似点进行了分析。有些人认为SOA有很多地方是值得微服务学习的&#xff0c;而有些人则认为区别对待微服务和SOA会更好。而Neal Ford认为&#xff0c;将单体迁移到面向服务的架构要比迁移到微服务来得容易。关于选…

考研生的努力程度是有多恐怖!

2021年全国研究生招生考试在12月26日开始&#xff0c;不过我没有参加。早就听闻考研生是多么多么的努力&#xff0c;今日一见&#xff0c;果然名不虚传&#xff0c;在这之前他们是有多努力我不知道&#xff0c;但是今天我所见到他们努力的程度&#xff0c;可以用恐怖来形容。偶…