首页 > 代码库 > 【leetcode】Add Two Numbers 解析以及拓展

【leetcode】Add Two Numbers 解析以及拓展

题目:

You are given two linked lists representing two non-negative numbers. 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.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

解析:题目很简单,输入两个链表,分别代表两个整数,每一个节点代表数字的每一位,从个位数开始计算,将每个节点的值相加即可,注意两个链表长度不同,以及最后有进位的情况,Java AC代码:

public class Solution {

	public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
		int carry = 0;
		ListNode res = new ListNode(-1);
		ListNode head = res;
		while (l1 != null || l2 != null) {
			int num = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val)
					+ carry;
			if(l1!=null){
				l1 = l1.next;
			}
			if(l2!=null){
				l2 = l2.next;
			}
			res.next = new ListNode(num % 10);
			res = res.next;
			carry = num / 10;
		}
		if(carry==1){
			res.next = new ListNode(1);
		}
		return head.next;
	}
}

拓展:如果输入的两个链表表示的数字不是从个位开始,而是从高位到低位,该如何处理呢?比如:

Input: (3->4->2)+(4->6->5)

Output: (8->0->7)

解析:拓展的这种解法看起来和原题差不多,实际上会更复杂更多,主要要注意两个问题。首先,因为两个链表的长度可能不一样,所以刚开始可以比较两个链表的长度,用0填充较短的链表;原题是求出新的节点后放在旧的节点后面,拓展题目需要添加节点到结果链表的头部,所以用递归调用解决。递归需要传递两个参数:结果链表节点和进位,可以创建内部类包含这两个参数,Java 实现代码如下所示:

/**
 * Input: (3->4->2)+(4->6->5) Output: (8->0->7)
 */

public class AddTwoNumbersExp {

	public static void main(String[] args) {
		ListNode node11 = new ListNode(3);
		ListNode node12 = new ListNode(4);
		ListNode node13 = new ListNode(2);
		ListNode node21 = new ListNode(4);
		ListNode node22 = new ListNode(6);
		ListNode node23 = new ListNode(5);
		node11.next = node12;
		node12.next = node13;
		node21.next = node22;
		node22.next = node23;
		ListNode res = new AddTwoNumbersExp().addTwoNumbers(node11, node21);
		while (res != null) {
			System.out.print(res.val+" ");
			res = res.next;
		}
	}

	public class Node {
		public ListNode sum = null;
		int carry;
	}

	public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

		// 查询两个链表长度,将短的链表用0填充
		int len1 = getLength(l1);
		int len2 = getLength(l2);
		l1 = len1 < len2 ? paddingZero(l1, len2 - len1) : l1;
		l2 = len2 < len1 ? paddingZero(l2, len1 - len2) : l2;

		// 对两个链表求和
		Node sum = addTwoList(l1, l2);

		// 判断是否有进位
		if (sum.carry == 0) {
			return sum.sum;
		}
		ListNode node = new ListNode(1);
		node.next = sum.sum;
		return node;

	}

	public int getLength(ListNode node) {
		int length = 0;
		while (node != null) {
			length++;
			node = node.next;
		}
		return length;
	}

	public ListNode paddingZero(ListNode l1, int zeroN) {
		ListNode res = new ListNode(-1);
		res.next = l1;
		for (int i = 0; i < zeroN; i++) {
			ListNode node = new ListNode(0);
			node.next = res.next;
			res.next = node;
		}
		return res.next;
	}

	public Node addTwoList(ListNode l1, ListNode l2) {
		if (l1 == null && l2 == null) {
			Node res = new Node();
			return res;
		}
		Node after = addTwoList(l1.next, l2.next);

		int val = after.carry + l1.val + l2.val;
		ListNode cur = new ListNode(val % 10);
		cur.next = after.sum;

		Node res = new Node();
		res.carry = val / 10;
		res.sum = cur;
		return res;
	}

}