1
+ /**
2
+ * Definition for singly-linked list.
3
+ * class ListNode {
4
+ * val: number
5
+ * next: ListNode | null
6
+ * constructor(val?: number, next?: ListNode | null) {
7
+ * this.val = (val===undefined ? 0 : val)
8
+ * this.next = (next===undefined ? null : next)
9
+ * }
10
+ * }
11
+ */
12
+
13
+ /**
14
+ * Leet Code 445.
15
+ *
16
+ * Solution uses an O(1) space aimed to reduce the required space for reversal or virtual reversal. It rather uses
17
+ * the length of the linked list to identify when a padding can be used and when can it be skipped. This step is done
18
+ * without the help of additional carry, since carry needs to be added in the reverse order.
19
+ *
20
+ * To adjust the carry pointer, we need to reverse the list, adjust the carry and reverse again.
21
+ *
22
+ * O(n) time for run-time, O(1) for space.
23
+ *
24
+ * @param l1
25
+ * @param l2
26
+ */
27
+ function addTwoNumbers ( l1 : ListNode | null , l2 : ListNode | null ) : ListNode | null {
28
+
29
+ // Finding the length of each linked list.
30
+ let l1Length = length ( l1 ) ;
31
+ let l2Length = length ( l2 ) ;
32
+
33
+ let resultCurr : ListNode | null = new ListNode ( 0 , null ) , resultHead = resultCurr , lastCurr : ListNode | null = resultCurr ;
34
+
35
+ // Adding items with prefixes attached, not using the carry.
36
+ while ( l1Length >= 0 && l2Length >= 0 && l1 !== null && l2 !== null ) {
37
+ if ( l1Length > l2Length ) {
38
+ // L1 has more items than l2, lets pull from l1 and add 0 for l2.
39
+ resultCurr . val = l1 . val ;
40
+ l1 = l1 . next ;
41
+ resultCurr . next = new ListNode ( 0 , null )
42
+ l1Length -- ;
43
+ } else if ( l1Length < l2Length ) {
44
+ // L2 has more items than l1, lets pull from l2 and add 0 for l1.
45
+ resultCurr . val = l2 . val ;
46
+ l2 = l2 . next ;
47
+ resultCurr . next = new ListNode ( 0 , null )
48
+ l2Length --
49
+ } else {
50
+ // Both have equal items, lets add.
51
+ resultCurr . val = l2 . val + l1 . val ;
52
+ l2 = l2 . next ; l1 = l1 . next ;
53
+ resultCurr . next = new ListNode ( 0 , null )
54
+ l2Length -- ; l1Length -- ;
55
+ }
56
+
57
+ lastCurr = resultCurr ;
58
+ resultCurr = resultCurr . next ;
59
+ }
60
+ lastCurr . next = null ;
61
+
62
+ let newHead = reverseLinkedList ( resultHead ) ;
63
+
64
+ // Adjust the carry now.
65
+ adjustCarry ( newHead )
66
+
67
+ // Reverse the list and return.
68
+ newHead = reverseLinkedList ( newHead ) ;
69
+
70
+ return newHead ;
71
+ } ;
72
+
73
+ function adjustCarry ( list : ListNode | null ) {
74
+ let curr = list , last = null , carry = 0 ;
75
+ while ( curr !== null ) {
76
+ const val = curr . val + carry ;
77
+ curr . val = val % 10 ;
78
+ carry = Math . floor ( val / 10 )
79
+ last = curr ;
80
+ curr = curr . next ;
81
+ }
82
+
83
+ // Add the pending carry to a new node.
84
+ if ( carry > 0 && last !== null ) {
85
+ last . next = new ListNode ( carry , null ) ;
86
+ }
87
+ }
88
+
89
+ function length ( l1 : ListNode | null ) {
90
+ let length = 0 , curr = l1 ;
91
+ while ( curr !== null ) {
92
+ length ++
93
+ curr = curr . next ;
94
+ }
95
+ return length ;
96
+ }
97
+
98
+ function reverseLinkedList ( l1 : ListNode | null ) {
99
+ let curr = l1 , last : ListNode | null = null ;
100
+ while ( curr !== null ) {
101
+ const next = curr . next ;
102
+ curr . next = last ;
103
+ last = curr ;
104
+ curr = next ;
105
+ }
106
+ return last ;
107
+ }
0 commit comments