题目思路:
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
我们知道题目已经限定了每个节点的值都不为负数了,所以我们就可以不考虑符号的问题了,那么就很简单了。
我们先看一下题目给的例子:
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。
从这个例子我们可以得到:
1、两个链表的长度可能不等,需要对齐
2、相加后可能需要进位
对齐进位
因为我们无法保证两个链表长度一致,所以我们干脆从后往前对齐,跟我们整数再做加法一样
方法一:反转链表
所以我们的入手则是对链表进行对齐,我们可以看到上面的图片,我们都是从后面开始对齐与计算的,所以很容易想到反转链表后进行相加。
public ListNode addInList (ListNode head1, ListNode head2) {
// 进行判空处理
if(head1 == null)
return head2;
if(head2 == null){
return head1;
}
// 反转h1链表
head1 = reverse(head1);
// 反转h2链表
head2 = reverse(head2);
// 创建新的链表头节点
ListNode head = new ListNode(-1);
ListNode nHead = head;
// 记录进位的数值
int tmp = 0;
while(head1 != null || head2 != null){
// val用来累加此时的数值(加数+加数+上一位的进位=当前总的数值)
int val = tmp;
// 当节点不为空的时候,则需要加上当前节点的值
if (head1 != null) {
val += head1.val;
head1 = head1.next;
}
// 当节点不为空的时候,则需要加上当前节点的值
if (head2 != null) {
val += head2.val;
head2 = head2.next;
}
// 求出进位
tmp = val/10;
// 进位后剩下的数值即为当前节点的数值
nHead.next = new ListNode(val%10);
// 下一个节点
nHead = nHead.next;
}
// 最后当两条链表都加完的时候,进位不为0的时候,则需要再加上这个进位
if(tmp > 0){
nHead.next = new ListNode(tmp);
}
// 重新反转回来返回
return reverse(head.next);
}
// 反转链表
ListNode reverse(ListNode head){
if(head == null)
return head;
ListNode cur = head;
ListNode node = null;
while(cur != null){
ListNode tail = cur.next;
cur.next = node;
node = cur;
cur = tail;
}
return node;
} 复杂度分析:
时间复杂度:方法一和二都为O(n)。取决于链表的长度。
空间复杂度:方法一没有用到额外的空间,所以为O(1)。
方法二:使用辅助栈
上一个方式是直接对原来的两个链表进行了反转,这个方法则是借助了栈的先进后出的特性来充当链表的反转,因为我们其实是想从两个链表的尾部进行开始操作,所以我们干脆直接将两条链表的结点放进栈中,然后依次出栈操作即可,然后相加完后采用头插法即可得到最终的链表。
public class Solution {
/**
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
public ListNode addInList (ListNode head1, ListNode head2) {
// write code here
if(head1 == null)
return head2;
if(head2 == null){
return head1;
}
// 使用两个辅助栈,利用栈先进后出,相当于反转了链表
Stack<ListNode> stack1 = new Stack<>();
Stack<ListNode> stack2 = new Stack<>();
ListNode p1=head1;
ListNode p2=head2;
// 将两个链表的结点入栈
while(p1!=null){
stack1.push(p1);
p1=p1.next;
}
while(p2!=null){
stack2.push(p2);
p2=p2.next;
}
// 进位
int tmp = 0;
// 创建新的链表头节点
ListNode head = new ListNode(-1);
ListNode nHead = head.next;
while(!stack1.isEmpty()||!stack2.isEmpty()){
// val用来累加此时的数值(加数+加数+上一位的进位=当前总的数值)
int val = tmp;
// 栈1不为空的时候,弹出结点并累加值
if (!stack1.isEmpty()) {
val += stack1.pop().val;
}
// 栈2不为空的时候,弹出结点并累加值
if (!stack2.isEmpty()) {
val += stack2.pop().val;
}
// 求出进位
tmp = val/10;
// 进位后剩下的数值即为当前节点的数值
ListNode node = new ListNode(val%10);
// 将结点插在头部
node.next = nHead;
nHead = node;
}
if(tmp > 0){
// 头插
ListNode node = new ListNode(tmp);
node.next = nHead;
nHead = node;
}
return nHead;
}
} 复杂度分析:
时间复杂度:方法一和二都为O(n)。取决于链表的长度。
空间复杂度:方法一没有用到额外的空间,所以为O(1),方法二用了栈则为O(n)。

京公网安备 11010502036488号