1. 题目描述
概述:两个逆序存储的非零开头的数字链表,求两数之和,输出也是逆序的链表
leetcode 01 02两个题分别考察了列表在物理存储层面的两种表示方式:数组和链表 的加法
2. 我的解法
暴力:按顺序同时遍历两个链表,按照进位规则进行加法运算,同时需要注意两个数维数不等,以及结果可能维数增加的情况 我的问题是,代码太过复杂:- a. 在初始化L3时,由于不是控制,需要另外计算存储值。应该设立空的表头,放到循环中值。
- b. 在循环之外,分别判断了当两个值不等长时的情况,可以归并到循环中,减少代码函数
1
/* Definition for singly-linked list.
2
* public class ListNode {
3
* int val;
4
* ListNode next;
5
* ListNode(int x) { val = x; }
6
* }
7
*/
8
class Solution {
9
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
10
int num=l1.val+l2.val;
11
ListNode l3 =new ListNode(num%10);
12
ListNode head=l3;
13
//同时遍历两个链表
14
while(l1.next!=null&&l2.next!=null)
15
{
16
l1=l1.next;
17
l2=l2.next;
18
num=l1.val+l2.val+num/10;//加上进位
19
l3.next=new ListNode(num%10);//超出10,求余
20
l3=l3.next;
21
}
22
//如果两个链表不等长,即两个数位数不同,剩下的分别遍历
23
while(l1.next!=null)
24
{
25
l1=l1.next;
26
num=l1.val+num/10;
27
l3.next=new ListNode(num%10);
28
l3=l3.next;
29
}
30
while(l2.next!=null)
31
{
32
l2=l2.next;
33
num=l2.val+num/10;
34
l3.next=new ListNode(num%10);
35
l3=l3.next;
36
}
37
//最后如果相加多出一位,别忘了加上
38
if(num/10!=0)
39
l3.next=new ListNode(num/10);
40
return head;
41
}
42
}
- 时间复杂度:O(max(m,n))
- 空间复杂度: O(max(m,n))
3. 解法二
解决我的解法的问题1
class ListNode {
2
int val;
3
ListNode next;
4
ListNode(int x) { val = x; }
5
}
6
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
7
ListNode dummyHead = new ListNode(0);//设置空的链表头
8
ListNode p = l1, q = l2, curr = dummyHead;
9
int carry = 0;
10
while (p != null || q != null) {
11
int x = (p != null) ? p.val : 0;//当不等长时,补充相应值0
12
int y = (q != null) ? q.val : 0;
13
int sum = carry + x + y;
14
carry = sum / 10;
15
curr.next = new ListNode(sum % 10);
16
curr = curr.next;
17
if (p != null) p = p.next;
18
if (q != null) q = q.next;
19
}
20
if (carry > 0) {
21
curr.next = new ListNode(carry);
22
}
23
return dummyHead.next;
24
}
时空复杂度不变
3. 扩展
如果链表存储的顺序反过来怎么办?
我首先想到的是链表先逆序计算,然后将结果再逆序呗,这就转换到我们之前的情况了。不知道还有没有其他的解法。3.1 下边是单链表逆序的代码。
1 | //逆序 |
2 | ListNode pre = null; |
3 | ListNode head = node; |
4 | while(head!=null) |
5 | { |
6 | ListNode next = head.next;//保留下一个节点,防丢失 |
7 | head.next =pre;//新head接上 |
8 | pre = head;//pre指针指向新head |
9 | head = next;//原列表更换head |
10 | } |