当前位置: 首页 > 科技观察

面试官:“算法写到最后,就用单链表做加法吧……”

时间:2023-03-21 10:16:10 科技观察

问:给定两个非空链表,表示两个非负整数。其中,各自的位数倒序存储,每个节点只能存储一位。将两个链表加在一起,并返回一个表示它们之和的新链表。例如:342+465=807两个数相加的问题处理的是最简单的数学加法运算,但是它是基于链表的,所以难点在于链表的处理。在加法运算中,除了要考虑每个位的加法,还需要考虑进位情况。对于这道题,链表的每个节点存储一个数,它是按照自然数倒序存储的,即从链的开始到结束的顺序保持从低到高,等于进位的方向和单链表的方向一致。由于单向链表的特点,没有前驱节点,也没有办法回溯。这道题的场景,从链头(低层)到链尾(高层)只需要一个while循环,就可以解决。但是需要注意carry的处理。计算完成后,每个节点需要根据10取余并存储。如果多了,需要携带到下一个节点参与运算。正好这也符合单链表的处理思路。然后我们需要几个变量,一个进位记录每个位操作后的进位,一个dummy节点记录两个链表相加后的链表节点。当我们到达最长链表的最后一个节点时,我们需要对进位做额外的处理。如果进位不为0,说明我们还要继续往高位进位,需要新建一个节点来存放进位。这里解释清楚了,直接贴代码。publicListNodeaddTwoNumbers(ListNode1,ListNode2){//存放计算结果的dummy节点ListNodedummy=newListNode(0);ListNodep=l1,q=l2,curr=dummy;//进位默认为0intcarry=0;//回车p和q链表指针的循环都结束while(p!=null||q!=null){intx=(p!=null)?p.val:0;inty=(q!=null)?q.val:0;//进位参与运算intsum=carry+x+y;//计算进位carry=sum/10;//构造一个新节点来存储计算出的数字值curr.next=newListNode(sum%10);curr=curr.next;if(p!=null)p=p.next;if(q!=null)q=q.next;}//处理最高位末尾进位if(carry>0){curr.next=newListNode(carry);}returndummy.next;}这里p和q分别用来存放链表l1和l2的节点,这是循环的基础。循环出的条件是两个链表都走到了尽头。在每个循环中,对每个节点的值进行处理并加上进位值,运算后将余数存入一个新的节点,并将新的进位值存入进位存储。最后需要注意的是,两个链表处理完成后,需要判断最高位是否需要进位(carry>0)。如有必要,创建一个新的链表节点来存储进位值。这个用链表做加法运算的问题这里就说明了,但是也有一些变体问题。如果链表不是按位倒序存储数字怎么办?如果是正序存储。例如:1→2→3+3→2→1=>123+321=?作者更多好文章