LeetCode - Linked List

Record the Linked List topic algorithm problems.

0002. Add Two Numbers

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.

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
const addTwoNumbers = (l1, l2) => {
let List = new ListNode(0);
let head = List;
let sum = 0;
let carry = 0;
while(l1 || l2 || sum){
if(l1) {
sum += l1.val;
l1 = l1.next;
}
if(l2) {
sum += l2.val;
l2 = l2.next;
}
if(sum >= 10 ){
carry = 1;
sum -= 10;
}
head.next = new ListNode(sum);
head = head.next;
sum = carry;
carry = 0;
}
return List.next;
};

Runtime: 108 ms
Memory Usage: 38.7 MB

0019. Remove Nth Node From End of List

Given a linked list, remove the n-th node from the end of list and return its head.
Example:
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Follow up:
Could you do this in one pass?

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
const removeNthFromEnd = (head, n) => {
let left, before, right = head;
left = before = {next: head};
while (n--) {
right = right.next;
}
while (right) {
right = right.next;
left = left.next;
}
left.next = left.next.next;
return before.next;
};

Runtime: 80 ms
Memory Usage: 34.1 MB

0021. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const mergeTwoLists = (l1, l2) => {
let mergedHead = { val : -1, next : null },
crt = mergedHead;
while(l1 && l2) {
if(l1.val > l2.val) {
crt.next = l2;
l2 = l2.next;
} else {
crt.next = l1;
l1 = l1.next;
}
crt = crt.next;
}
crt.next = l1 || l2;

return mergedHead.next;
};

Runtime: 68 ms
Memory Usage: 35.5 MB

0023. Merge k Sorted Lists

You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.

Example 1:
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6
Example 2:
Input: lists = []
Output: []
Example 3:
Input: lists = [[]]
Output: []

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function mergeLists(a, b) {
const dummy = new ListNode(0);
let temp = dummy;
while (a !== null && b !== null) {
if (a.val < b.val) {
temp.next = a;
a = a.next;
} else {
temp.next = b;
b = b.next;
}
temp = temp.next;
}
if (a !== null) {
temp.next = a;
}
if (b !== null) {
temp.next = b;
}
return dummy.next;
}

const mergeKLists = (lists) => {
if (lists.length === 0 ) {
return null;
}
while (lists.length > 1) {
let a = lists.shift();
let b = lists.shift();
const h = mergeLists(a, b);
lists.push(h);
}
return lists[0];
};

Runtime: 108 ms
Memory Usage: 42.8 MB

0138. Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
The Linked List is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:
val: an integer representing Node.val
random_index: the index of the node (range from 0 to n-1) where random pointer points to, or null if it does not point to any node.
Example 1:
Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]
Example 2:
Input: head = [[1,1],[2,1]]
Output: [[1,1],[2,1]]
Example 3:
Input: head = [[3,null],[3,0],[3,null]]
Output: [[3,null],[3,0],[3,null]]
Example 4:
Input: head = []
Output: []
Explanation: Given linked list is empty (null pointer), so return null.
Constraints:
-10000 <= Node.val <= 10000
Node.random is null or pointing to a node in the linked list.
Number of Nodes will not exceed 1000.

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const copyRandomList = (head) => {
if(!head) {
return null;
}
const clones = new Map();
let n = head;
while(n) {
clones.set(n, new Node(n.val));
n = n.next
}
n = head;
while(n) {
clones.get(n).next = clones.get(n.next) || null;
clones.get(n).random = clones.get(n.random) || null;
n = n.next
}
return clones.get(head);
};

Runtime: 56 ms
Memory Usage: 35.2 MB

0141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

solution 1:

1
2
3
4
5
6
7
8
9
10
11
const hasCycle = (head) => {
const nodes = new Set();
while (head) {
if (nodes.has(head)) {
return true;
}
nodes.add(head);
head = head.next;
}
return false;
};

Runtime: 72 ms
Memory Usage: 37.8 MB

solution 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
const hasCycle = (head) => {
let fast = head;
let slow = head;

while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
return true;
}
}
return false;
};

Runtime: 60 ms
Memory Usage: 36.6 MB

0142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const detectCycle = (head) => {
let slow = head;
let fast = head;
while (slow && fast && fast.next) {
slow = slow.next;
fast = fast.next.next;

if (slow === fast) {
while (head !== fast) {
head = head.next;
fast = fast.next;
}
return head;
}
}
return null;
};

Runtime: 68 ms
Memory Usage: 36.8 MB

0148. Sort List

Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3
Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0
Output: -1->0->3->4->5

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const sortList = (head) => {
if (head === null || head.next === null) {
return head;
}
let fast = head.next;
let slow = head;
while (fast !== null && fast.next !== null) {
fast = fast.next.next;
slow = slow.next;
}
const mid = slow.next;
slow.next = null;
let left = sortList(head);
let right = sortList(mid);
const dummy = new ListNode(0);
let h = dummy;
while (left !== null && right !== null) {
if (left.val < right.val) {
h.next = left;
left = left.next;
} else {
h.next = right;
right = right.next;
}
h = h.next;
}
if (left) {
h.next = left;
}
if (right) {
h.next = right;
}
return dummy.next;
};

Runtime: 76 ms
Memory Usage: 40.4 MB

0160. Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins.
Example 1:
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node’s value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
Example 2:
Input: intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Reference of the node with value = 2
Input Explanation: The intersected node’s value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [0,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.
Example 3:
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.
Notes:
If the two linked lists have no intersection at all, return null.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const getIntersectionNode = (headA, headB) => {
if (!headA || !headB) {
return null;
}
let p1 = headA;
let p2 = headB;
while (p1 && p2 && p1 !== p2) {
p1 = p1.next;
p2 = p2.next;
if (p1 == p2) {
return p1;
}
if (!p1) {
p1 = headB;
}
if (!p2) {
p2 = headA;
}
}
return p1;
};

Runtime: 88 ms
Memory Usage: 43 MB

0206. Reverse Linked List

Reverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
Follow up:
A linked list can be reversed either iteratively or recursively. Could you implement both?

solution 1:

1
2
3
4
5
6
7
8
9
10
const reverseList = (head) => {
let prev = null;
while (head) {
const next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
};

Runtime: 60 ms
Memory Usage: 34.9 MB

solution 2:

1
2
3
4
5
6
7
8
9
const reverseList = (head) => {
if (!head || !head.next) {
return head;
}
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
};

Runtime: 48 ms
Memory Usage: 35.2 MB

0234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2
Output: false
Example 2:
Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?

solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const isPalindrome = (head) => {
let fast = head;
let slow = head;

// Set slow to the head of the second half
while (fast) {
fast = fast.next ? fast.next.next : fast.next;
slow = slow.next;
}

// Reverse the second half
let prev = null;
while (slow) {
const next = slow.next;
slow.next = prev;
prev = slow;
slow = next;
}

// Compare the two halves in sequence
while (prev) {
if (prev.val !== head.val) {
return false;
}
prev = prev.next;
head = head.next;
}

return true;
};

Runtime: 60 ms
Memory Usage: 39.3 MB

0237. Delete Node in a Linked List

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Given linked list – head = [4,5,1,9].
Example 1:
Input: head = [4,5,1,9], node = 5
Output: [4,1,9]
Explanation: You are given the second node with value 5, the linked list should become 4 -> 1 -> 9 after calling your function.
Example 2:
Input: head = [4,5,1,9], node = 1
Output: [4,5,9]
Explanation: You are given the third node with value 1, the linked list should become 4 -> 5 -> 9 after calling your function.

solution :

1
2
3
4
const deleteNode = (node) => {
node.val = node.next.val;
node.next = node.next.next;
};

Runtime: 60 ms
Memory Usage: 35.7 MB