链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 节点代码

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 

 

 

 

 

 完整代码:

  <1> 链表实现代码

class ListNode {
 int val; // 数据域
 ListNode next; // 指针域,指向下?个节点
 ListNode() {
 }
 ListNode(int x) {
 val = x;
 }
}

  <2>存在 long 类型溢出的问题,需要?动测试

/**
 * 暴?解法:
 * 遍历两个链表使?数学思维分别将他们转成整数
 * 对两个整数进?求和得到sum
 * 将sum按照数学思维再转成链表
 * ?动测试:
 * 若超过语??持的数据类型范围,则报错
 * 解决办法:BigInteger
 *
 *
 * @param l1
 * @param l2
 * @return
 */
 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 //把链表转成数字,注意次序为逆序
 long l1Value = 0;
 int digit = 0;
 while (l1 != null) {
//该位对应的 单位
 int pow = (int) Math.pow(10, digit);
 //在当前数值基础上增加新的?个?位
 l1Value += (long)l1.val * pow;
 digit++;
 //链表指向下?个节点
 l1 = l1.next;
 }
 long l2Value = 0;
 digit = 0;
 while (l2 != null) {
 //该位对应的 单位
 int pow = (int) Math.pow(10, digit);
 //在当前数值基础上增加新的?个?位
 l2Value += (long)l2.val * pow;
 digit++;
 //链表指向下?个节点
 l2 = l2.next;
 }
 //创建?个新链表,头部为空节点
 ListNode head = new ListNode();
 ListNode cur = head;
 //数字相加
 long sum = l1Value + l2Value;
 if (sum == 0) {
 head = new ListNode(0);
 return head;
 }
 //数字再转成链表
 while (sum > 0) {
 //每次取当前最低位
 int val = (int) (sum % 10);
 //移除最低位
 sum = sum / 10;
 //创建新节点
 ListNode node = new ListNode(val);
 //插?链表尾部
 cur.next = node;
 //链表尾部指针移动
 cur = cur.next;
 }
 return head.next;
 }

  <3>解决办法:? java.math.BigInteger 替代 long 类型。注意全类名写法。

/**
* 暴?解法:存在的问题:使?long也会存在溢出
* 解决办法:java.math.BigInteger
* 该类在leetcode默认环境没有导?,所以使?全类名编写
*
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 //把链表转成数字,注意次序为逆序
 java.math.BigInteger l1Value = java.math.BigInteger.valueOf(0);
 int digit = 0;
 while (l1 != null) {
 java.math.BigInteger carry =
java.math.BigInteger.valueOf(10).pow(digit);
 l1Value =
l1Value.add(carry.multiply(java.math.BigInteger.valueOf(l1.val)));
 digit++;
 l1 = l1.next;
 }
 java.math.BigInteger l2Value = java.math.BigInteger.valueOf(0);
 digit = 0;
 while (l2 != null) {
 java.math.BigInteger carry =
java.math.BigInteger.valueOf(10).pow(digit);
 l2Value =
l2Value.add(carry.multiply(java.math.BigInteger.valueOf(l2.val)));
 digit++;
 l2 = l2.next;
 }
 ListNode head = new ListNode();
 ListNode cur = head;
 //数字相加,然后再转成链表
 java.math.BigInteger sum = l1Value.add(l2Value);
 if (sum.compareTo(java.math.BigInteger.valueOf(0)) == 0) {
 head = new ListNode(0);
 return head;
 }
 while (sum.compareTo(java.math.BigInteger.valueOf(0)) > 0) {
 int val = sum.mod(java.math.BigInteger.valueOf(10)).intValue();
 sum = sum.divide(java.math.BigInteger.valueOf(10));
 ListNode node = new ListNode((int) val);
 cur.next = node;
 cur = cur.next;
 }
 return head.next;
}

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 完整代码:

 /**
 * 最优解:数学思维解法
 * 1.遍历两个链表
 * 2.对应位置的节点数值相加
 * 3.将计算结果插?新链表尾部
 * ?于10,则进位,将进位加到下个节点
 *
 * 边界问题
 * 两个链表边界:next==null
 * 细节问题
 * 两个链表?度不?致,短链表?位视为0
 * 链表最?位发?进位,结果链表需要增加?个节点存放进位数字
 *
 * @param l1
 * @param l2
 * @return
 */
 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
 ListNode p = l1, q = l2; // 原链表的两个遍历指针
 ListNode resultHead = new ListNode(-1); // 结果链表的头结点head
 ListNode curr = resultHead; // 结果链表的遍历指针,代表当前操作的节点
 int carry = 0; // 进位
 // 1.遍历两个链表
 while (p != null || q != null) { // 以?链表为准
 // 获取当前节点的值:链表较短,已?节点,取0
 int x = p != null ? p.val : 0;
 int y = q != null ? q.val : 0;
 // 2.对应位置的节点数值相加
 int sum = x + y + carry;
 carry = sum / 10; // 如何得到进位:和对10求整,得到此次计算的进位
 int num = sum % 10; // 存放到新链表节点中的数值
 // 3.将计算结果插?新链表尾部
 curr.next = new ListNode(num); // 创建新节点
 curr = curr.next;
 p = p == null ? p : p.next;
 q = q == null ? q : q.next;
 }
 if (carry > 0) { // 处理进位节点
 curr.next = new ListNode(carry);
 }
 return resultHead.next;
}

测试用例

<1>辅助数据结构:链表。代码如下:

class ListNode {
 int val; // 数据域
 ListNode next; // 指针域,指向下?个节点
 ListNode() {
 }
 ListNode(int x) {
 val = x;
 }
}

<2>测试?例:

输?:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

<3>测试代码:

public static void main(String[] args) {
 Solution solution=new AddTwoNumbers2().new Solution();
 int[] arr1 = {2, 4, 3};
 int[] arr2 = {5, 6, 4};
 ListNode l1 = new AddTwoNumbers2().new ListNode();
 ListNode l2 = new AddTwoNumbers2().new ListNode();
 ListNode l1Cur = l1;
 ListNode l2Cur = l2;
 for (int i = 0; i < arr1.length; i++) {
 ListNode node1 = new AddTwoNumbers2().new ListNode(arr1[i]);
 ListNode node2 = new AddTwoNumbers2().new ListNode(arr2[i]);
 l1Cur.next = node1;
 l1Cur = node1;
 l2Cur.next = node2;
 l2Cur = node2;
}
 ListNode result = solution.addTwoNumbers(l1.next, l2.next);
 while (result != null) {
 System.out.print(result.val + " "); // 输出:7 0 8
 result = result.next;
 }
 }

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

 链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

 

链表+数学:实现两个大数相加 ( Leetcode 02/67/371/445/989 )

上一篇:leetcode 817. 链表组件


下一篇:Swagger2使用