Linked List
Disclaimer
This article is originally based on my understanding of this concept. No guarantee on the accuracy.😅
Comparing with Array, linked list dosen’t support accessing by index. So for searching a certain element, the complexcity is O(n).
The linked list doesn’t took up continuous space in memory, so for inserting/deleting element, the complexcity is O(1)
Using two pointer can help to reduce the complexity.
For loop in the list, using fast and slow pointers.
206. 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?
iterative
1
2
3
4
5
6
7
8
9
10
11
12
13var reverseList = function (head) {
if (!head || !head.next) return head;
let pre = null,
cur = head;
while (cur) {
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
head = pre;
return head;
};recursive
1
2
3
4
5
6
7
8var reverseList = function (head) {
if (!head || !head.next) return head;
let next = head.next;
let reversedHead = reverseList(next);
head.next = null;
next.next = head;
return reversedHead;
};
21. 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
- iterative (two pointer)
1 | var mergeTwoLists = function (l1, l2) { |
Recursive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function mergeTwoLists(l1, l2) { //always compare two node
if(l1 === null) { //if it reaches the end return the other node
return l2
}
if(l2 === null) {
return l1
}
if(l1.val <= l2.val) {
l1.next = mergeTwoLists(l1.next, l2) //let the next head point to the next result
//pass the new head l1.next
return l1 //return the smaller one
} else {
l2.next = mergeTwoLists(l2.next, l1) //pass the new head l2.next
return l2
}
}
160. Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins.
Input: intersectVal = 8,
listA = [4,1,8,4,5],
listB = [5,0,1,8,4,5],
skipA = 2, skipB = 3Output: 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.
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.
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.
1 | var getIntersectionNode = function (headA, headB) { |
141. 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.
Follow up: Can you solve it using O(1) (i.e. constant) memory?
Use slow & fast pointers:
Space complexity :O(1) Time complexcity: O(n)
1 | var hasCycle = function(head) { |
Using the list to store a marker/flag to indicate if this node was traversed.
Space&Time complexcity: O(N)
1 | var hasCycle = function(head) { |
234. 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?
Two pointer:
1 | var isPalindrome = function (head) { |
Using stack:
1 | var isPalindrome = function (head) { |
148. 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
Merge sorting:
It’s easy to just apply the Divided Conqure algorithm template 😁
1 | var sortList = function (head) { |
19. 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
Given n will always be valid.
Two Pointers:
the faster one is n step ahead of the slower one. Then they move forwards together. When the fast pointer reaches the end, the slow pointer is pointing to the nth element from end of list.
1 | var removeNthFromEnd = function (head, n) { |
2. 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.
1 | var addTwoNumbers = function (l1, l2) { |