Sort List, Insertion Sort List, Reverse Linked List, Palindrome Linked List, Delete Node in a Linked List, Remove Linked List Elements, Intersection of Two Linked Lists, Reorder List, Copy List with Random Pointer
Sort a linked list in O(n log n) time using constant space complexity.
Solution
Merge sort: use merge two sorted list as helper function.
Corner case: if only one node left, just return the head to be merged
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
publicstatic ListNode mergetwosortedlist(ListNode a, ListNode b){
ListNode head = new ListNode(0);
ListNode h=head;
while(a!= null && b!=null){
if(a.val>b.val){
h.next=b;
b=b.next;
}
else{
h.next=a;
a=a.next;
}
h=h.next;
}
if(a==null) h.next=b;
else h.next=a;
return head;
}
public ListNode sortList(ListNode head) {
if(head==null || head.next==null) return head;
ListNode fast=head;
ListNode slow=head;
while(fast.next!=null && fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
fast=slow.next;//fast now points to mid
slow.next=null;
slow=sortList(head);//sort first half
fast=sortList(fast);//sort second half
return mergetwosortedlist(slow, fast);
}
Insertion Sort List
Sort a linked list using insertion sort.
Solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public ListNode insertionSortList(ListNode head) {
ListNode pre=head, cur=head, post=head;
if(head==null || head.next==null) return head;
ListNode dummyhead=new ListNode(0);
while(cur!=null){
ListNode tmp=dummyhead;
while(tmp.next!=null && tmp.next.val<cur.val){
tmp=tmp.next;
}
//now tmp is before the element larger than cur, need to insert cur before
post=cur.next;
cur.next=tmp.next;
tmp.next=cur;
cur=post;
}
return dummyhead.next;
}
Reverse Linked List
Reverse a singly linked list. click to show more hints. Hint: A linked list can be reversed either iteratively or recursively. Could you implement both?
Iterative Solution
1
2
3
4
5
6
7
8
9
10
11
public ListNode reverseList(ListNode head) {
if(head==null) return head;
ListNode cur=head, post=head, pre=null;
while(cur!=null){
post=cur.next;
cur.next=pre;
pre=cur;
cur=post;
}
return pre;
}
Recursive Solution
1
2
3
4
5
6
7
8
public ListNode reverseList(ListNode head) {
if(head==null || head.next==null) return head;
ListNode post=head.next;
ListNode subhead=reverseList(post);
post.next=head;
head.next=null;
return subhead;
}
Palindrome Linked List
Given a singly linked list, determine if it is a palindrome. Follow up: Could you do it in O(n) time and O(1) space?
Solution o(n) space
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicstaticbooleanisPalindrome(ListNode head) {
if(head==null) returntrue;
ListNode slow=head, fast=head;
Stack<Integer> stk=new Stack<Integer>();
stk.push(head.val);
while(fast.next!=null && fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
stk.push(slow.val);
}
//slow is now at the lower median
if(fast.next==null && !stk.isEmpty()) stk.pop();//odd number, pop median
slow=slow.next;
while(slow!=null){
if(slow.val!=stk.pop()) returnfalse;
slow=slow.next;
}
returntrue;
}
Solution o(1) space
reverse last half of the list when we reached median, compare each node
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
publicstaticbooleanisPalindrome(ListNode head) {
if(head==null || head.next==null) returntrue;
ListNode slow=head, fast=head;
while(fast.next!=null && fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
//slow is now at the lower median
slow=slow.next;
ListNode pre=null, cur=slow, post=cur;
while(cur!=null){
post=cur.next;
cur.next=pre;
pre=cur;
cur=post;
}
while(head!=null && pre!=null){
if(head.val!=pre.val) returnfalse;
head=head.next;
pre=pre.next;
}
returntrue;
}
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. Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
Solution
1
2
3
4
5
publicvoiddeleteNode(ListNode node) {
if(node==null || node.next==null) return; //tails dont matter
node.val = node.next.val;
node.next = node.next.next;
}
Remove Linked List Elements
Remove all elements from a linked list of integers that have value val. Example Given: 1 —> 2 —> 6 —> 3 —> 4 —> 5 —> 6, val = 6 Return: 1 —> 2 —> 3 —> 4 —> 5 Credits: Special thanks to @mithmatt for adding this problem and creating all test cases.
Solution
1
2
3
4
5
6
7
8
9
10
11
12
public ListNode removeElements(ListNode head, int val) {
ListNode dummyhead=new ListNode(0);
dummyhead.next=head;
ListNode cur=dummyhead;
while(cur!=null && cur.next!=null){
if(cur.next.val==val){
cur.next=cur.next.next;
}
else cur=cur.next; // use else here because we want to keep checking continuous vals
}
return dummyhead.next;
}
Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins.
1
2
3
4
5
6
7
8
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin tointersectat node c1.
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
find length of two lists, and skip the longer list until starting from same length
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
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lena=0, lenb=0;
ListNode cura=headA, curb=headB;
while(cura!=null){
cura=cura.next;
lena++;
}
while(curb!=null){
curb=curb.next;
lenb++;
}
cura=headA;
curb=headB;
if(lena>lenb){
for(int i=0;i<(lena-lenb);i++){
cura=cura.next;
}
}
else{
for(int i=0;i<(lenb-lena);i++){
curb=curb.next;
}
}
while(cura!=null && curb!=null){
if(cura.val==curb.val) return cura;
cura=cura.next;
curb=curb.next;
}
returnnull;
}
Cycle Solution
+Two pointer solution (O(n+m) running time, O(1) memory): Maintain two pointers pA and pB initialized at the head of A and B, respectively. Then let them both traverse through the lists, one node at a time. When pA reaches the end of a list, then redirect it to the head of B (yes, B, that’s right.); similarly when pB reaches the end of a list, redirect it the head of A. If at any point pA meets pB, then pA/pB is the intersection node. To see why the above trick would work, consider the following two lists: A = {1,3,5,7,9,11} and B = {2,4,9,11}, which are intersected at node ‘9’. Since B.length (=4) < A.length (=6), pB would reach the end of the merged list first, because pB traverses exactly 2 nodes less than pA does. By redirecting pB to head A, and pA to head B, we now ask pB to travel exactly 2 more nodes than pA would. So in the second iteration, they are guaranteed to reach the intersection node at the same time. If two lists have intersection, then their last nodes must be the same one. So when pA/pB reaches the end of a list, record the last element of A/B respectively. If the two last elements are not the same one, then the two lists have no intersections.
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
35
36
37
38
39
40
41
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
returnnull;
}
ListNode pA = headA;
ListNode pB = headB;
ListNode tailA = null;
ListNode tailB = null;
while (true) {
if (pA == null) {
pA = headB;
}
if (pB == null) {
pB = headA;
}
if (pA.next == null) {
tailA = pA;
}
if (pB.next == null) {
tailB = pB;
}
//The two links have different tails. So just return null;
Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do this in-place without altering the nodes’ values. For example, Given {1,2,3,4}, reorder it to {1,4,2,3}.
Solution
find median, reverse second half, merge two parts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
publicstaticvoidreorderList(ListNode head) {
if(head==null || head.next==null) return;
ListNode slow=head, fast=head;
while(fast.next!=null && fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
ListNode cur=slow.next, post=cur, pre=null;
slow.next=null;
while(cur!=null){
post=cur.next;
cur.next=pre;
pre=cur;
cur=post;
}
while(pre!=null && head!=null){
post=head.next;
head.next=pre;
pre=pre.next;
head.next.next=post;
head=post;
}
}
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.