2. 两数相加
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.
这道题目先给出解决算法。后面再讲测试方法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// 先补齐位置。解决两个数位数上不相等的问题
setNewListNode(l1, l2);
ListNode ln = new ListNode(0);
int sum = 0;
ListNode l3 = ln;
while (l1 != null && l2 != null) {
sum = l1.val + l2.val;
ListNode lx = new ListNode(sum);
ln.val = lx.val;
if (l1.next != null && l2.next != null)
ln.next = lx;
ln = ln.next;
l1 = l1.next;
l2 = l2.next;
}
// printLink(l3);
l3 = getJin1(l3);
return l3;
}
private static void setNewListNode(ListNode l1, ListNode l2) {
int size1 = getLinkSize(l1);
int size2 = getLinkSize(l2);
if (size1 == size2)
return;
int max = Math.max(size1, size2);
if (max == size1)
setZeroToLink(l2, size2, max);
else if (max == size2)
setZeroToLink(l1, size1, max);
}
private static void setZeroToLink(ListNode lx, int size, int max) {
while (lx != null) {
// 遍历到最后一个结点
if (lx.next == null) {
for (int i = size; i < max; i++) {
ListNode l0 = new ListNode(0);
lx.next = l0;
lx = lx.next;
}
break;
}
lx = lx.next;
}
}
// 每个结点值进1处理
private static ListNode getJin1(ListNode l3) {
ListNode ln = l3;
int jin = 0;
while (ln != null) {
ln.val += jin;
if (ln.val / 10 == 1) {
ln.val = ln.val % 10;
// 要是下一个为空。1要新建一个结点放在下一个位置
jin = 1;
if(ln.next == null)
{
ListNode x = new ListNode(jin);
ln.next = x;
break;
}
}
else
{
jin = 0;
}
ln = ln.next;
}
return l3;
}
// 获取链表结点的尺寸
public static int getLinkSize(ListNode ln) {
int size = 0;
while (ln != null) {
size++;
ln = ln.next;
}
return size;
}
}
先理解一下这道题目。这道题目的总体原理和上小学我们做加法运算一样,两个数相加。先从两个数的个位数加起来...直到加到最后一个数:
比如:285+ 173
两个数的个位: 5+3 = 8
两个数的十位: 8+7 = 15 (15>10) =15%10 = 5
两个数的百位:2+1+1(上面十位相加进1) = 4
结果是:458
链表输出:(8 —> 5—> 4)
输入两个数(位数不一定相等),然后这两个数位数逆序,转换成链表,例如:
255->(5—>5—>2)
+432->(2—>3—>4)
=687->(7—>8—>6)
两个数相加,就是两个链表的每个对应的值相加 。最后得出所要的第三个链表。
我的解题步骤:
1.先补齐两个链表的结点,使它们的位数相等:因为两个数不一定相等。这样链表的结点也不相同。补齐的思路是,给比较结点数比较小的链表往末端添加0。这样子就能使两个链表结点数相等,方便后面相加
2.两个数对应的结点相加。得到的结果就是所求链表的结点值。这里我先允许相加结果大于10。等到最后构建完结果链表,再对链表做进位处理
3.得出的链表就是所要的结果
4.关键位置在于对链表结构要熟悉,在遍历的时候才不会出错
测试方法main:
1.添加一个自然数逆序转换位链表的方法:
reserveNumToListNode(int num)
2.添加一个打印列表的方法:
void printLink(ListNode ln)
public class ChainTest {
public static void main(String[] args) {
int num1 = 255;
int num2 = 432;
ListNode ln1 = reserveNumToListNode(num1);
ListNode ln2 = reserveNumToListNode(num2);
printLink(ln1);
printLink(ln2);
ListNode ln3 = addTwoNumbers(ln1, ln2);
printLink(ln3);
}
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// 先补齐位置。解决两个数位数上不相等的问题
setNewListNode(l1, l2);
ListNode ln = new ListNode(0);
int sum = 0;
ListNode l3 = ln;
while (l1 != null && l2 != null) {
sum = l1.val + l2.val;
ListNode lx = new ListNode(sum);
ln.val = lx.val;
if (l1.next != null && l2.next != null) {
ln.next = lx;
}
ln = ln.next;
l1 = l1.next;
l2 = l2.next;
}
l3 = getJin1(l3);
return l3;
}
private static void setNewListNode(ListNode l1, ListNode l2) {
int size1 = getLinkSize(l1);
int size2 = getLinkSize(l2);
if (size1 == size2) {
return;
}
int max = Math.max(size1, size2);
if (max == size1) {
setZeroToLink(l2, size2, max);
} else if (max == size2) {
setZeroToLink(l1, size1, max);
}
}
private static void setZeroToLink(ListNode lx, int size, int max) {
while (lx != null) {
// 遍历到最后一个结点
if (lx.next == null) {
for (int i = size; i < max; i++) {
ListNode l0 = new ListNode(0);
lx.next = l0;
lx = lx.next;
}
break;
}
lx = lx.next;
}
}
// 每个结点值进1处理
private static ListNode getJin1(ListNode l3) {
ListNode ln = l3;
int jin = 0;
while (ln != null) {
ln.val += jin;
if (ln.val / 10 == 1) {
ln.val = ln.val % 10;
jin = 1;
// 要是下一个为空。1要新建一个结点放在下一个位置
if (ln.next == null) {
ListNode x = new ListNode(jin);
ln.next = x;
break;
}
} else {
jin = 0;
}
ln = ln.next;
}
return l3;
}
// 获取链表结点的尺寸
public static int getLinkSize(ListNode ln) {
int size = 0;
while (ln != null) {
size++;
ln = ln.next;
}
return size;
}
private static void printLink(ListNode ln) {
System.out.print("(");
while (ln != null) {
System.out.print(ln.val);
if (ln.next != null) {
System.out.print("—>");
}
ln = ln.next;
}
System.out.println(")");
}
// 345+678;
// 整数的逆序转换为链表结点----重载:long为形参
private static ListNode reserveNumToListNode(long num) {
ListNode ln = new ListNode(0);
// 建立一个遍历lx,辅助链表ln的插入
ListNode lx = ln;
long tmp = num;
while (tmp != 0) {
int val = (int) (tmp % 10);
ListNode x = new ListNode(val);
lx.val = x.val;
if (tmp / 10 != 0)
lx.next = x;
lx = lx.next;
tmp /= 10;
}
return ln;
}
private static ListNode reserveNumToListNode(int num) {
ListNode ln = new ListNode(0);
// 建立一个遍历lx,辅助链表ln的插入
ListNode lx = ln;
int tmp = num;
while (tmp != 0) {
int val = tmp % 10;
ListNode x = new ListNode(val);
lx.val = x.val;
if (tmp / 10 != 0)
lx.next = x;
lx = lx.next;
tmp /= 10;
}
return ln;
}
}
class ListNode {
int val;
ListNode next;
public ListNode(int x) {
this.val = x;
}
}