找回密码
 立即注册
查看: 248|回复: 0

从算法角度看代码的优化:整数反转

[复制链接]
发表于 2023-3-13 07:29 | 显示全部楼层 |阅读模式


题目来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/reverse-integer
难度:简单
题目描述

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32位的有符号整数的范围 [231, 231  1] ,就返回 0。
假设环境不允许存储 64位整数(有符号或无符号)。
示例 1:
输入:x = 123输出:321示例 2:
输入:x =-123输出:-321示例 3:
输入:x = 120输出:21示例 4:
输入:x =0输出:0提示:

  • -2^31 <= x <= 2^31 - 1
解题过程

第一次提交

拿到这个题我的第一反应是将数值转成字符串,然后反向输出字符串,然后再将字符串转为整数,当然会判断整数是否包含符号,所以我的第一次提交也是这样的思路:
classSolution{publicintreverse(intx){if(x==0){return0;}StringvalueOf=String.valueOf(x);char[]chars;StringBuildernumberBuilder;if(valueOf.startsWith("-")||valueOf.startsWith("+")){chars=valueOf.substring(1).toCharArray();numberBuilder=newStringBuilder(valueOf.substring(0,1));}else{chars=valueOf.toCharArray();numberBuilder=newStringBuilder();}for(inti=chars.length-1;i>=0;i--){numberBuilder.append(chars);}intresult=0;try{result=Integer.parseInt(numberBuilder.toString());}catch(NumberFormatExceptione){returnresult;}returnresult;}}虽然所有测试用例都通过了,但是代码很长,而且性能也不好:




第二次提交

然后我考虑换种解法,先想到的是递归,但是由于要用过程值,所以递归是行不通的,这里走了好多弯路。但你如果只是像反向打印输出一个整数的话,是可以用递归算法的:
publicstaticvoidprintOut(intn){if(n>=10){printOut(n/10);}System.out.println(n%10);}比如输出12333,打印结果:


接着,我反向推到了下过程,理清了思路:上次余数乘以10,加上本次余数,但是每一次的被除数都是上次的商,比如211,反转后是112,第一次的余数是1,商是21,下一次的被除数是21余数是是1,商是2,再下一次被除数是2,余数是2,商是0,这时候就结束了。将上面的流程整理成代码是这样的:
classSolution{publicstaticintreverse(inti){longresult=0;while(i!=0){intyu=i%10;result=result*10+yu;i=i/10;}return(int)result==result?(int)result:0;}}代码更简洁了,而且性能也比上面更好:




只是逻辑上更复杂更抽象了,但只要你理清了思路,上面的代码你也可以写出来。
代码优化

你觉得上面的代码还有优化的空间吗?其实还可以优化成这样:
classSolution{publicstaticintreverse(inti){longresult=0;while(i!=0){result=result*10+i%10;i=i/10;}return(int)result==result?(int)result:0;}}虽然,相比第二次提交其实就只删除了一个变量,但代码的内存消耗方面的性能表现更好了:


优化前,内存消耗是35.5 MB,优化之后35.3MB,第一次提交的执行用时: 3 ms,内存消耗: 35.8 MB,从这一点上看,代码的优化是非常必须的,毕竟系统崩溃的时候没有一行代码是无辜的
总结

算法算是一个特别特别基础,但是又特别考验编程实力的技能,随着这项技能的不断提升和精进,你不仅可以写出更高效,更健壮的系统,同时你考虑问题的角度也会比别人更专业,更有深度,而这些是与系统、与语言无关的;从更实际的角度来说,当你算法能力够强的时候,你在写业务代码的时候也会尽可能减少不必要对象的的创建、冗余代码,因为你知道每一个不必要的操作,对系统而言都是不必要内存的消耗,都为系统的崩溃埋下了雷,今天的算法优化就很好地体现了这一点。
我知道,坚持学习本身很难,偶尔(就刚刚)我也想放纵一下,想躺着的玩手机,想啥都不干,但是当我硬着头皮站在新的起跑线上的时候,当我开始做这件事的时候,我觉得我又可以了,我觉得坚持过当下就好……
而且当我静下心来的时候,我觉得娱乐和放纵本身并不能给我满足,当一切的想法都得到满足的时候,反而会让我感受到更大失落、空洞……
现在的我,坚持的意义就是靠输出倒逼自己输入,如果非要找一个坚持的理由,那就是我不满意自己当下的生活,我想做自己觉得对的事,我希望通过这些事让自己的生活更充实,更有意义,未来某一天,我希望自己回首这段时光的时候,心怀感激,满心欢喜。
当然,有时候我也会很困惑,很迷茫,不知道应该分享些什么,不知道应该如何学习,感觉自己似乎进入到了一个封闭的空间,不知道该往哪里去,也不知道该如何摆脱这一切?
但当每一个阳光明媚的早上来临的时候,一切又可以重新开始了,一切都充满了希望。在我的认知里,我觉得自己是一个积极乐观的人,我相信明天,我相信未来,我总相信事情都会越来越好,也想想越努力越幸运,所以我不想给自己的人生设限,不想给自己贴标签,但我会坚持自己的选择,按照自己的节奏用心生活,我特别喜欢罗曼罗兰的一句话——有一种英雄主义就是认清了生活的真相,却依然热爱它。
现在我把这句话也送给你,也许生活很残酷,超出了你的认知极限,黑暗、肮脏、毁三观,但依然有人在用心生活,深处泥淖,依然有人在仰望星空;也许生活很美好,充满了欢声笑语,让你感受到满心欢喜,但依然有人选择放弃生命,放弃希望。倒不是说你必须成为什么样的人,做什么事,只是希望你知道自己在做什么,自己想做什么,此时此刻你是否对当下的生活满意,毕竟生活的点点滴滴都是选择,遵循内心最真实的感受,最真实的想法,或坚持,或放弃,只要你感觉舒适就好,只要你觉得值得就好,至于其他人说什么倒是无足轻重的了……
- END -

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-16 16:38 , Processed in 0.268856 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表