题目:给你两个非空的链表(linked lists),表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
这道题可是困扰了我快一天的时间。刚入手,对leetcode的一些基本认识不够。后来才知道,即便是leetcode的playground给出特别全的代码,也没法直接拿过来在pycharm或者jupyter上运行,leetcode里好多代码都没显示出来。所以要提交的内容只是包括了两个listnode的加法,至于怎么将一组list或者string转化成链表,以及将链表打印出来,这些过程则不在要提交的内容里。不过我在这写东西,不是作为要提交到leetcode上的标准答案来写,所以,我打算从头到尾模拟一下,如何将输入的string或者list转化成链表,怎样对链表按照题目要求进行计算,以及最后如何将链表打印出来。
什么是链表,可以直接看数据结构--链表,所以对链表的介绍直接跳过。根据题目要求,任意输入一个数,然后将输入数的每位数字逆序存储在链表的node中,每个node只储存一位数,也就是0-9中的一个,所以要先定义链表里的node,然后将输入的值转化为node中存储的值。linked lists里的node是一个类,对node的定义如下:
通过定义可以看出,每个node由两个部分组成:元素+指针,也就是value和next。
接下来,我们定义如何将输入的数存储到linked lists的node里。我们假设输入的数已经转化成list了,那么接下来就是将list转化成linked lists的形式,如果输入的数是其他形式,比如string,则再额外加一步转化成list即可。下面是将list转化为linked lists的函数:
这样,list里的每一位数都储存在link lists里了,增加的linked lists的长度就是list的长度。这里dummy root是构造linked lists常用的一种形式,将dummy root作为一个参照,每次指向下一个node从而按要求构造好linked lists, 而dummy node就相当于构造的链表的头结点。
在转化为linked lists之后,接下来就是运算步骤,即,将两个数相加得到新的数这一过程。我将leetcode上一位答主的回答搬过来了,写的真简洁,佩服!
运算是对每个node进行的,举个例子,我们要算98+998,那linked lists应该存储为 和。运算就是先算8+8,得6进1,然后再算9+9+1,得9进1,再1+9得0进1,所以最后的结果为,也是一个linked lists。
这一运算过程,首先需要一个新的linked lists来储存运算结果,记为p,同时也需要一个s来判断是否有进位1,如果有,则需在下一位的运算中加上1,没有则加0。接下来则是每一位的计算,如果某一linked lists被遍历完了,则在接下来的遍历过程,该linked lists的元素参与加法的位置一直是None,比如在上面那个例子,98所在的linked lists先被遍历完,那在第三位数的运算中,就成了0(None)+9+1。(l1.val if l1 else 0)这一句的意思是,如果l1被遍历完了,则在计算中此位置取0,否则取l1当前值。终止条件为l1和l2都被遍历完,同时s为0,最后再返回到p的第一个node。
到这步,其实任务已经完成了,输出的就是储存了运算结果的linked lists,但是为了可视化,我接下来再进行一步print的过程。
在将linked lists打印出来的过程中,我这里是直接转化成list了,如果输入的linked lists是空的,打印成0,如果不是空的,则按照linked lists每个node的值,相应地打印到list里,这样就实现了打印过程。
额外补充一下,如果希望输入和输出是string的形式,应该怎么办。在输入的时候,将string转化成list即可,需要用到json包。不能直接用list函数,否则会连逗号以及括号都打印出来,几个运行结果如下:
再就是将linked list输出为string,这里只需将函数listNodeTolist()改成listNodeToString()即可。
之前忘了,98+998的运行结果: