@@ -11,16 +11,13 @@ export { removeNthFromEnd };
1111// To do this in one iteration, throw all the nodes onto a list. Then we can easily find the nth node from the end of
1212// the list. After that, we just have to point the (k - 1)th node to the (k + 1)th node. Assuming both exist.
1313//
14+ // You can also do this using two pointers, but this solution is a more straightforward.
15+ //
1416// COMPLEXITY:
1517//
1618// Runs in O(n) time because we are iterating through the list once. Runs in O(n) space because we are storing the list
1719// in an array.
1820function removeNthFromEnd ( head : ListNode | null , n : number ) : ListNode | null {
19- // Assume this means we aren't going to remove anything.
20- if ( n === 0 || head === null ) {
21- return head ;
22- }
23-
2421 // Just convert the linked list to an array so we can easily find the nth node from the end.
2522 const list : ListNode [ ] = [ ] ;
2623 let node : ListNode | null = head ;
@@ -29,37 +26,33 @@ function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
2926 node = node . next ;
3027 }
3128
32- // Okay, now we try to find the nth node from the end of the list. First make sure we can actually do this. That is,
33- // n must be between 1 and the length of the list inclusive.
34- if ( n > list . length ) {
29+ // Now make sure this operation can even be done. If n is 0 or greater than the length of the list, then we can't
30+ // then we can't remove anything!
31+ if ( head === null || n <= 0 || n > list . length ) {
3532 return head ;
3633 }
3734
38- // Special case the single element list to make things easier (here, n === 1).
39- if ( list . length === 1 ) {
40- return null ;
41- }
35+ // Create sentinel nodes to make the logic easier, and so we can return the head of the list later.
36+ const sentinel = new ListNode ( ) ;
37+ sentinel . next = head ;
4238
4339 // Now that we know n is within bounds, let's find the node we want to remove. For example, if we want to remove the
4440 // 2nd node from the end of the list with 3 elements, then the index is 1 (3 - 2 = 1).
4541 //
4642 // After this we just have point the (k - 1)th node to the (k + 1)th node. Assuming both exist.
4743 const k = list . length - n ;
4844
49- // If the (k + 1)th node doesn't exist, then we are unlinking the tail of the list. AKA n === 1.
50- if ( k + 1 === list . length ) {
51- list [ k - 1 ] . next = null ;
52- return head ;
53- }
45+ // The previous node to remove is the a = (k - 1)th node. If it turns out the (k - 1)th node doesn't exist, then node
46+ // a is the sentinel node we created.
47+ const a = list [ k - 1 ] ?? sentinel ;
5448
55- // If the (k - 1)th node doesn't exist, then we are unlinking the head of the list. AKA n === stack.length.
56- //
57- // We can just return head.next as that's the new head.
58- if ( k - 1 < 0 ) {
59- return head . next ;
60- }
49+ // The next node to link it to is the c = (k + 1)th node. If it turns out that the (k + 1)th node doesn't exist, then
50+ // node c is null.
51+ const c = list [ k + 1 ] ?? null ;
52+
53+ // Unlink the node b in position list[k] by setting the a node's next pointer to c.
54+ a . next = c ;
6155
62- // Otherwise just make the (k - 1)th node point to the (k + 1)th node.
63- list [ k - 1 ] . next = list [ k + 1 ] ;
64- return head ;
56+ // Return the list minus the sentinel.
57+ return sentinel . next ;
6558}
0 commit comments