算法5:LeetCode ——两数相加

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;
	}
}



猜你喜欢

转载自blog.csdn.net/u012184326/article/details/80289998
今日推荐