LeetCode刷题笔记-2.两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
实例1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
提示:
- 每个链表中的节点数在范围 [1, 100] 内
- 0 <= Node.val <= 9
- 题目数据保证列表表示的数字不含前导零
辅助方法
在解这道题的之前我先写了两个方法,一个是将int数组,转换成ListNode对象,第二个是ListNode的toString方法,用来友好的输出ListNode对象。
/**
* 将int数组转换为ListNode对象
*/
public static ListNode intArrayConvertNode(int[] arrays) {
ListNode head = null;
ListNode tail = null;
for (int val : arrays) {
ListNode node = new ListNode(val);
if (head == null) {
head = node;
} else {
tail.next = node;
}
tail = node;
}
return head;
}
定义一个head和tail两个对象,分别用来代表链表的头节点和尾结点。开始时head和tail都为空,开始第一个转换时head为null,这时head和tail都指向新节点node,以后每次添加节点,都是在tail的后面添加即:tail.next = node,然后再将tail置为新的尾部即:tail = node。head始终指向第一个节点。
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
ListNode next = this;
while (next != null) {
builder.append(next.val);
next = next.next;
if (next != null) {
builder.append(",");
}
}
return builder.toString();
}
最终解法
我的解法
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode resultNode = new ListNode();
ListNode tail = resultNode;
// 初始进位为0
int carry = 0;
while (l1 != null || l2 != null) {
ListNode newNode = new ListNode();
// 若其中有一个队列的next为空则以0代替
int val1 = l1 == null ? 0 : l1.val;
int val2 = l2 == null ? 0 : l2.val;
// 每次都要计算进位(初始为0 相当于不用计算)
int sum = val1 + val2 + carry;
// 进位已经被加入结果,重置为0
carry = 0;
//计算出的结果大于等于10,那么只取余数,然后设置进位
if (sum >= 10) {
int r = sum % 10;
carry = sum / 10;
newNode.val = r;
} else {
//小于10 不用处理
newNode.val = sum;
}
// 向尾部入列
tail.next = newNode;
tail = newNode;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
// 若最终还有进位没有被消耗,则新增一位
if (carry != 0) {
tail.next = new ListNode(carry);
}
return resultNode.next;
}
复杂度分析
- 时间复杂度:O(max(m,n))其中 m和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要O(1) 的时间。
- 空间复杂度:O(1)。注意返回值不计入空间复杂度。
官方解法
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null, tail = null;
int carry = 0;
while (l1 != null || l2 != null) {
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
int sum = n1 + n2 + carry;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
}
}
复杂度分析
- 时间复杂度:O(max(m,n))其中 m和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要O(1) 的时间。
- 空间复杂度:O(1)。注意返回值不计入空间复杂度。
总结
我和官方的解法差不多,但是官方的更加简洁一些,比如:不需要判断sum大于10小于10的情况,直接用sum % 10
的结果即可,1%10 = 1 11%10=1
其实是一样的。
LeetCode刷题笔记-2.两数相加
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/1001