很久没做算法题了,准备重操旧业,于是刷了一波LeetCode,看到一个比较经典的链表算法题,分享出来。

题目


给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807



链表结构



class ListNode{
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
    }
}



三个需要操作的链表图示(其实可以使用两个链表以节省空间,但是时间效率就会降低,题目没有定义链表长度)

                                                     

到倒数第三个的长度String java_java

 

 

 

这都是没有进位而且输入链表长度相同且结果不影响输出链表长度的情况,如果需要进位,或者输入链表的长度不同,那么也需要考虑进去。

                                                       

到倒数第三个的长度String java_数据结构与算法_02

思路

我们很容易想到就是从左往右依次遍历两个输入的List,对这两个List的Node对应加和,但是要注意的就是进位问题和这里的数字是反向的,注意进位判断,其实这个反向的条件对我们是有利的,因为这和我们平常加法算数是一致的,从低位到高位,这里只不过改成从左往右了,原理都是一样的。

还要注意输入链表的最后一个结点位置,我们用循环来遍历的时候就需要每一次都检查链表是不是最后一个结点,而且两个链表长度未必一样,注意空引用判断。

主要逻辑代码



1 public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 2         ListNode l4 = new ListNode(0);
 3         ListNode l3 = new ListNode(0);
 4         l4.next = l3;
 5 
 6         while(l1 != null || l2 != null){
 7             int val1 = l1 == null ? 0 : l1.val;
 8             int val2 = l2 == null ? 0 : l2.val;
 9             //创建新的结点
10             ListNode l5 = new ListNode(0);
11             //进位
12             l5.val = (val1 + val2 + l3.val)/10;
13             //当前位
14             l3.val = (val1 + val2 + l3.val)%10;
15 
16             //如果是最后一次循环,且最后一位为0,那么就要除去这个结点
17             if(l5.val == 0 && (l1!= null ? l1.next:null) == null && (l2 != null ? l2.next : null) == null){
18                 l3.next = null;
19             }else{
20                 l3.next = l5;
21                 l3 = l5;
22             }
23 
24             //跳转指针
25             l1 = l1 == null ? null : l1.next;
26             l2 = l2 == null ? null : l2.next;
27         }
28         return l4.next;
29     }



 

测试代码



class ListNode{
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
    }
}
public class Test{

    public static void main(String[] args) {
        ListNode l1 = new ListNode(2);
        ListNode l2 = new ListNode(3);
        ListNode l3 = new ListNode(4);
        l1.next=l2;
        l2.next=l3;
        l3.next = null;
        ListNode l4 = new ListNode(5);
        ListNode l5 = new ListNode(6);
        ListNode l6 = new ListNode(4);
        l4.next = l5;
        l5.next = l6;
        l6.next = null;

        printList(addTwoNumbers(l1,l4));
    }

    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode l4 = new ListNode(0);
        ListNode l3 = new ListNode(0);
        l4.next = l3;

        while(l1 != null || l2 != null){
            int val1 = l1 == null ? 0 : l1.val;
            int val2 = l2 == null ? 0 : l2.val;
            //创建新的结点
            ListNode l5 = new ListNode(0);
            //进位
            l5.val = (val1 + val2 + l3.val)/10;
            //当前位
            l3.val = (val1 + val2 + l3.val)%10;

            //如果是最后一次循环,且最后一位为0,那么就要除去这个结点
            if(l5.val == 0 && (l1!= null ? l1.next:null) == null && (l2 != null ? l2.next : null) == null){
                l3.next = null;
            }else{
                l3.next = l5;
                l3 = l5;
            }

            //跳转指针
            l1 = l1 == null ? null : l1.next;
            l2 = l2 == null ? null : l2.next;
        }
        return l4.next;
    }

    public static void printList(ListNode l){
        while(l!=null){
            System.out.print("->");
            System.out.print(l.val);
            l = l.next;
        }
    }
}