
LeetCode 上第一题和第二题你会讲么?
阿粉最近也在刷 LeetCode 上面的题,因为 LeetCode 的题,很多都是在注重算法的实践上,殊不知,阿粉在前几道题目上就写出了像是垃圾一样的代码。看了其他的代码,瞬间感觉为什么自己没有思考出来这么好的方法呢?
LeetCode 第一题
LeetCode 上面的第一道题,也是入门基础的题,求和。
给定一个数组和一个目标和,从数组中找两个数字相加等于目标和,输出这两个数字的下标。
这个题是什么意思呢?相信大家肯定也都知道,给你个数组,数组里面有一堆的数据,然后再给你一个数,找出数组里面相加等于这个数字的元素,并且把元素位置输出出来。
阿粉看到这个基础题目,心里在想,非常简单呀,直接双层循环,然后计算求和相等就输出就完事了,尴尬了,阿粉写出了一种最暴力的写法,写法如下:
这是阿粉第一时间想到的方案,阿粉当时也冥思苦想还有没有其他的方案来实现,但是阿粉太low ,没有想到其他的解决方案,于是阿粉就开始所有,然后看看大家都是怎么想的,于是乎,发现了自己的想法确实还和广大网友差距不小呀,确实,阿粉的实现方式没什么错误,因为题目就是求和,功能实现了,但是效率缺是真的低,因为两层 for 循环。
时间复杂度:两层 for 循环,O(n²)
求和方法二
我们第一种方法的关键在于代码的这个地方:
这个地方,我们使用的是加法,那么有没有可能使用减法呢?
于是第二种算法就来了
阿粉当时就感觉,果然,人外有人,天外有天呀,这不看不知道,算法不单单有这个循环的方式呀,如果不用循环的话,我们能不能有方法来实现这个求和的算法呢?
有,而且还是我们经常见到的,而且也是面试里面会经常被问到的,那就是 HashTablle 了。
我们可以把数组的每个元素保存为 hash 的 key,下标保存为 hash 的 value 。
这样只需判断 sub 在不在 hash 的 key 里就可以了,而此时的时间复杂度仅为 O(1)!
需要注意的地方是,还需判断找到的元素不是当前元素,因为题目里讲一个元素只能用一次。
那么代码是应该怎么实现呢?
时间复杂度:比解法一少了一个 for 循环,降为 O(n)
空间复杂度:所谓的空间换时间,这里就能体现出来, 开辟了一个 hashtable ,空间复杂度变为 O(n)
题目比较简单,毕竟暴力也可以解决,唯一的亮点就是从时间的复杂度变得稍微缓和了一点 ,对于集合hash的使用,如果是在面试环节,你写出了不一样的操作,相信会亮眼一波。
LeetCode 第二题
如果第一题是基础,阿粉相信第二题,绝对属于那种摸不着头脑的,就像 最近比较火的 “羊了个羊”,第一关秒杀,第二关直接凉透了。
问题如下:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
这直接从简单难度直线上升到高级难度了,其实这只是一个稍微比简单难度高了一点点的。
图示如下:
链表最左边表示个位数,代表 342 + 465 =807
我们应该怎么思考这个问题:
在看到这道题时,第一想法是逐个遍历链表的节点,将每个节点的数据取出并存储到String类型的数据中,再将这些String类型的字符数据拼接起来反转后再成int类型的数据。但是后来发现这么做是不对的,应该先定义一条新的链表按节点来逐个存储两条链表相加的值,最后将这条新的链表返回。
创建一条新的链表,设置两个头指针current和result,在两条链表相加的过程中只移动current指针,result指针不移动,最后将result返回。两条链表节点的值在相加时会有进位的情况,因此要进位的数与不进位的数(即剩余的数)进行获取和存储,因此再定义用来存储需要进位的int类型的变量total和存储不需要进位的数值的int类型变量remainder,将两个变量的初值均定义为0。
代码如下:
说实话阿粉确实是没有想到,后来完全是看了解析答案之后,才能完整的滤通这个代码,你们也是这样么?你也有刷题的习惯么?欢迎大家踊跃回答。
本文转载自公众号:java极客技术
