所在的位置: 数据结构 >> 学习内容 >> CodeSnippetAdd

CodeSnippetAdd

陈列在LeetCode上的第二道算法题,为AddTwoNumbers,乍一看标题觉得这题也应该蛮容易的,题目边上标注的难度值为中等,于是点进去查看这题要做什么,这不看不知道,一看彻底傻眼……

[2,4,3]+[5,6,4]=[7,0,8],我能说刚看到这个例子的时候完全没辙了么……第一个可以理解,2+5=7,那么4+6=10什么情况会是0呢?这个也简单,就是对10取余的时候,但接下来的问题在于,为什么最后一个3+4=8?

先抛开这个例子,来看下C#编码情况下,网站提供的方法是怎么样的:

给定了ListNode的定义,在AddTwoNumbers方法中传入两个ListNode,然后进行一定操作之后返回一个新的ListNode。

既然标题标注的就是两个数的相加,那么我们可以完全肯定,上面对之前例子的解析不会有问题,计算2+5,4+6,3+4,其中肯定要对相加后的值取余,但问题是最后一个如何得到8,或许这个才是关键的步骤。

与其迷惑,不如先把能想到的写出来,于是得到了如下的代码:

上面这段代码的思路是怎么来的?首先,既然要返回一个ListNode,那么毫无疑问需要定义出一个ListNode,这里定义一个head,并将它初始化成第一个元素,接下来就是对传入的两个ListNode进行操作,操作无非是相加,那么,循环条件肯定是两个ListNode至少有一个不为空,这个好理解,如果两个都是空的,那直接返回空的ListNode就完成了。

真正需要认真思考的逻辑是在while的循环里,这个逻辑也不难,如果l1元素存在,则取出来,不存在则置为0,将值放在x中,同样的l2也是如此,将值存放于y中,之后要做的就是无论x,y值为多少都相加,而我们的目标则是将最终的sum对10取余,并将值存在新的ListNode中,一旦ListNode有值了,便将指针指向下一个待存元素即head.next。

现在除了最后一个3+4的值会不一样之外,我们看这段代码,应该是没有任何问题了,也就是说预期值为[7,0,7],现在指定测试用例并且运行代码看下结果:

什么?我们的答案返回的是空的……怎么可能?回代码看下哪里出了问题,艾玛,我们前面是将head初始化成为ListNode(0)的,直接head.next=newListNode(sum%10),然后head=head.next真的行得通么?这里先留下这个疑问,我们就简单的试着再定义一个变量试试是不是可以解决这个问题,再来思考为什么……于是代码变成下面这样:

这里先忽略命名规则,定义一个a,这是个人的习惯,在尝试做什么的时候,个人喜欢随意点,等到确认代码通过没问题之后,再将该代码进行一定的重构,包括命名的更新,删除多余的代码,调整代码的格式等等。闲话不多说,赶紧试一试结果:

这里我们得到的结果是[7,0,7],和我们之前的预期是一样的,当然,和题目的期望值还是有差距的,接下来就是调试代码,寻求为什么答案会是[7,0,8]?如果这个问题想不通,估计这题也就到此为止了……这是件令人悲伤的事……

先来看下在3+4之前发生了什么,计算3+4之前代码计算了4+6,这里不由得令人想起儿时学算术的时候老师提到的进位,进位是说两个一位数相加得到两位数的时候需要向前进一位,如果套用在这里,有没有可能将这个进位留在了接下来要相加的两个数的和之中呢?

不管了,先这么尝试吧,天知道这个思路是带我们走向光明还是走向更深的绝望……由于两个一位数相加,最大的情况是9+9,也就是只会向前进一位,且数字为1,那么,我们假设一个变量,它可能的情况只有0和1,只要两个数的值小于10就为0,大于10则为1,先试试吧……于是代码变成如下形式:

试运行下测试用例,看是否符合预期:

完美~这样的话,至少这个测试用例通过了,根据第一次编码的经验,这个网站会提供蛮多的测试用例的,而要想验证是否通过所有测试用例,简单的做法就是直接提交代码:

错误的答案,继续调试代码看问题出在哪里……5+5=10,根据上面我们一步一步做下来,可以知道,预期是0,因为sum%10的结果,为什么这里还会有多一个1呢?1是从哪里来的,前面我们通过假设知道了,肯定是那个进位b剩余下来的值,按理说它需要放在下一组数相加的时候累加,但这里由于l1,l2都为空了,所以这个数就弄丢了,现在要做的就是把这个数找回来……怎么找,这个简单,判断b是不是等于1就可以了,如果l1,l2都空了,但b等于1的时候,只需要再写一个值到新的ListNode中,于是只需要将while的条件改成while(l1!=null

l2!=null

b==1),重新提交代码看下结果:

这个结果居然是正确的,也就是说,这题考验的知识点是数学中的进位问题,与我们认知的进位有一点区别,但又是何其相似~此时对代码进行重构,进位的英文为carry,得到的代码如下:

正式提交代码接受答案看看通过了多少个测试用例:

哇噻,一共个测试用例,这道题的用例还真的是蛮丰富的,换成是从事软件测试的自己,试问能想出多少测试用例呢……hmm...对自己暂且不予置评……

结束了么?还没有哦,前面我们还遗留了一个问题,为什么直接用head.next=newListNode(sum%10),然后head=head.next的时候得到的答案为空,而引入一个pre之后就解决了这个问题呢?相信这个问题并不是难题,如果不懂的话,可以翻翻数据结构的书籍,这里就不赘述了,也让大家留些时间思考~^_^

后记:

这题乍看之下简单,审题时却容易被3+4=8给迷惑,如果想不到与数位进位有关,估计这题就没有合适的解决方案了,至于怎么样能想到数位进位,其实我也不知道为什么能想到,只是觉得前面遇到了一个4+6,所以想到是不是可以试一下,如果这个思路行不通,或许我会寻求网络的帮助,因为自己确实没有其他思路了……

最后送上一句话:只要有思路,就勇敢尝试,要知道通往成功的路上难免失败,而我们要做的,就是不惧失败的前行~









































中科白癜风微博
怎样治疗白癜风呢



转载请注明:http://www.92nongye.com/xxnr/204613114.html