LeetCode-3:链表相加问题
这个题目属于中等难度
到底难在哪里呢
第一,基础便是如何理解链表的含义,看了题干才发现链表原来是一个对象链接一个对象,对象与对象之间通过next方法相连,而next方法对应的刚好是下一个对象,实际是val对应变量,next对应指针,取一个val,指针next左移一下。
第二,如何将链表相加并输出?
实际来言,它的输出顺序并不关键,关键点在于如何实现相加。
最早我的思路是,将两个链表先通过string保存下来,再将string转为Long或者Double类型数据,然后直接相加,再把得到的数据转为一个长字符串,然后从低到高循环这个字符串的char,一步步将它转换为链表。
看着是不是没啥问题?
但是很容易遇到暴力溢出的问题,原因在于,java中Long和Double最大支持精度范围只有64bit,也就是最大支持的精确十进制数只有2^63,即便是双精度,也不会比这个大!
一直出现溢出问题之后,我才发现这个问题的真正难点在于,即通过链表这一结构类型,实现任意长数字的加法。
任意长!
暂时看下来,链表没有长度限制。他的计算位数可以远超Long等包装数据类型。还有一个点是,各种数据在内存里面的存取是不是刚好和链表相同?
官方思路:
-
对于任意一个链表,都通过LinkList.next 是否为null来判断是否到头,到头了,说明LinkList.val已经被加到计算里面去了,然后记findL1linklistEnd = true;下次不加也再也去找L1.next;
- 关于java中指针的概念:从此题目中,如何把链表反向以高bit最后放到尾巴上为最终目的。
如何理解: 开始新建两个链表,第一个链表 = 第二个链表,它们的其实指针地址相同,然后反复把第二个链表的尾巴向后延伸,最后再返回第一个链表,那么第一个链表的值,被第二个循环的延长了;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode resultListNode = null; ListNode endListNode = null; int add2NextBit = 0; boolean findL2End = false; boolean findL1End = false; while (true) { int bitValueL1 = 0; int bitValueL2 = 0; if(!findL1End) {bitValueL1 = l1.val;} if(!findL2End) {bitValueL2 = l2.val;} if (findL1End && findL2End && add2NextBit == 0) { break; } int bitValue = bitValueL1 + bitValueL2 + add2NextBit; if (bitValue >= 10) { add2NextBit = 1; } else { add2NextBit = 0; } if (resultListNode != null) { // resultListNode = new ListNode(bitValue % 10, resultListNode); endListNode.next = new ListNode(bitValue % 10); endListNode = endListNode.next; } else { resultListNode = new ListNode(bitValue % 10); endListNode = resultListNode; } if (!findL1End) { l1 = l1.next; if (l1==null) {findL1End = true;} } if (!findL2End) { l2 = l2.next; if (l2==null) {findL2End = true;} } } return resultListNode; }
这个思路击败了99%的选手:
我的原始code 击败21%的选手 = =。
code view:
下面的code有多个影响速度的问题:
1. 利用try catch来增加容错,防止出现意外,结果就是这个逻辑非常慢,大概增加了 26ms时间(相比2ms);
2. 开始新建链表,输出结果为反的,最后又负负得正,这个方法好理解,就是先正着放,然后再先入先出;大概增加3ms时间;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode resultListNode = null; int add2NextBit = 0; boolean findL2End = false; boolean findL1End = false; while (true) { int bitValueL1 = 0; int bitValueL2 = 0; if(!findL1End) { try { bitValueL1 = l1.val; // System.out.print( "bitValueL1 = "+bitValueL1); } catch (Exception e) { findL1End = true; bitValueL1 = 0; } } if(!findL2End) { try { bitValueL2 = l2.val; // System.out.println( "; bitValueL2 = "+bitValueL2); }catch (Exception e) { findL2End = true; bitValueL2 = 0; } } if (findL1End && findL2End && add2NextBit == 0) { break; } int bitValue = bitValueL1 + bitValueL2 + add2NextBit; if (bitValue >= 10) { add2NextBit = 1; } else { add2NextBit = 0; } if (resultListNode != null) { resultListNode = new ListNode(bitValue % 10, resultListNode); } else { resultListNode = new ListNode(bitValue % 10); } try { l1 = l1.next; } catch (Exception e) { findL1End = true; } try { l2 = l2.next; } catch (Exception e) { findL2End = true; } } ListNode reverseListNode = null; while (true) { if (reverseListNode ==null) { reverseListNode = new ListNode(resultListNode.val); }else { reverseListNode = new ListNode(resultListNode.val,reverseListNode); } if (resultListNode.next == null) { break; } resultListNode = resultListNode.next; } return reverseListNode; }
总结:
再一次体会到和大家的差距,学习到很多,感谢!