Linked List 🌼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ListNode {
// 结点的值
int val;

// 下一个结点
ListNode next;

// 节点的构造函数(无参)
public ListNode() {
}

// 节点的构造函数(有一个参数)
public ListNode(int val) {
this.val = val;
}

// 节点的构造函数(有两个参数)
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}

203. Remove Linked List Elements

Easy

  • Example :

    img

    1
    2
    Input: head = [1,2,6,3,4,5,6], val = 6
    Output: [1,2,3,4,5]

🌟Coding:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
*!!! dummy head is always very handy , try to use it as much as possible
* 添加虚节点方式
* 时间复杂度 O(n)
* 空间复杂度 O(1)
* @param head
* @param val
* @return
*/
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return head;
}
// 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
while (cur != null) {
if(cur.val == val){
pre.next = cur.next;
cur = cur.next;
}else{
pre = pre.next;
cur = cur.next;
}
}
return dummy.next; //!!!! notice, here you want to return dummy.next not head
}
/**
* 不添加虚拟节点方式
* 时间复杂度 O(n)
* 空间复杂度 O(1)
* @param head
* @param val
* @return
*/
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val) {
head = head.next;
}
// 已经为null,提前退出
if (head == null) {
return head;
}
// 已确定当前head.val != val
ListNode pre = head;
ListNode cur = head.next;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return head;
}
/**
* 不添加虚拟节点and pre Node方式
* 时间复杂度 O(n)
* 空间复杂度 O(1)
* @param head
* @param val
* @return
*/

//MY WAY:
//this step is to delete all the val that is in the beginning og the list
while(head != null && head.val == val)
/* this step is necessary because when you go through the list
current list can only delete its next list, can't delete itself. */
head = head.next;
ListNode curr = head;
while(curr != null && curr.next != null){
if(curr.next.val == val )
curr.next = curr.next.next;
else{
curr = curr.next;
}
}
return head;
//my way 2:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dumb = new ListNode(0, head);
ListNode pointer = dumb;
//if(head == null) return head;
while(pointer.next != null){
if(pointer.next.val == val){
pointer.next = pointer.next.next;
}else{
pointer = pointer.next; // 注意这句话在else里面
}
}
return dumb.next; // here is dumb.next not head
}
}

707. Design Linked List

medium

🌟Coding:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
ListNode(int val , ListNode next) {
this.val = val;
this.next = next;
}
}
class MyLinkedList {
int size;
ListNode head;

public MyLinkedList() {
size = 0;
head = new ListNode(0); //!!!!!!!!!!!!! dummy head
}

public int get(int index) {
if(index < 0 || index >= size) return -1;
ListNode point = head;
while(index >= 0){
point = point.next;
index --;
}
return point.val;
}

public void addAtHead(int val) {
addAtIndex(0,val);
//size ++;
}

public void addAtTail(int val) {
addAtIndex(size,val);
//size ++ ;
}

public void addAtIndex(int index, int val) {
ListNode add = new ListNode(val);
if(index < 0 || index > size) return ;
ListNode point = head;
while(index > 0){
point = point.next;
index--;
}
add.next = point.next;
point.next = add;
size++;//!!!!!!!
}

public void deleteAtIndex(int index) {

if(index < 0 || index >= size ) return ; // >=size not >= size - 1
ListNode point = head;
while(index > 0){
point = point.next;
index --;
}
if(point.next != null){
point.next = point.next.next;
}else{
point.next = null;
}
size --; //!!!!!!!!!!

}

}

/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/

206. Reverse Linked List

easy

Example :

img

1
2
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]

img

🌟Coding:

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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode temp = null;
ListNode cur = head;
while(cur != null){
temp = cur.next; //notice: here need a temp to keep track of cur.next
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
//return pre not cur, cause cur is the null linkedNote after the whole linkedList

}
}

24. Swap Nodes in Pairs

Medium

Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list’s nodes

Example :

img

1
2
Input: head = [1,2,3,4]
Output: [2,1,4,3]

🌟Coding:

24.两两交换链表中的节点2

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
42
43
44
45
46
47
// WRONG!!! Draw a graph then you will see why this method is stupidly wrong.
// Here we have to use a dummy head.
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode firstnode = head;
ListNode temp;
ListNode secondnode;
while (firstnode != null && firstnode.next != null && firstnode.next.next != null) {
temp = firstnode.next.next;
secondnode = firstnode.next;

secondnode.next = firstnode;
firstnode.next = temp.next;
firstnode = temp;
}
return head;

}
}

// Below is the right solution (=
// if you use dummy head then you don't need to cosider the special situations like the start of the link and the end of the link. It makes coding more simple
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null) return head;
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy;
ListNode first ;
ListNode second ;
ListNode temp;
while(cur.next != null && cur.next.next != null){
first = cur.next; //
second = first.next; //
temp =second.next; // i feel like those three lines need attention, do this at the beginning of the iteration!
//我觉得这个申明放在while的最前面而不是后面是因为它可以检查最开始进入循环的时候cur是不是空的情况

second.next = first;

first.next = temp;
cur.next = second;

cur = first;
}
return dummy.next;

}
}

second try, even it’s right, but you need to consider a lot of situations which makes the coding complicated.这个方法每次循环横跨了四个linkedlist.

therefore, the first approach is way better

so when you do the loop, you dont want the 循环跨度太大,不然你得考虑很多特殊情况。

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
42
43
44
45
46
47
48
49
50
class Solution {
public ListNode swapPairs(ListNode head) {
// Check if the list is empty or has only one element
if (head == null || head.next == null) {
return head;
}

// Initialize the result as the second node
ListNode res = head.next;

// Initialize pointers for swapping
ListNode first = head;
ListNode second = head.next;
ListNode third = head.next.next;

// Swap pairs while traversing the list
while (true) {
// Swap the first and second nodes
second.next = first;

// Check if there's a third node
if (third != null) {
// Check if there's a fourth node
if (third.next != null) {
first.next = third.next;
} else {
first.next = third;
}
} else {
first.next = null;
}

// If there are no more nodes to swap, return the result
if (first.next == null) {
return res;
}

// Update pointers for the next pair of nodes
first = third;
second = first.next;

// Check if there's a third node for the next pair
if (second.next != null) {
third = second.next;
} else {
third = null;
}
}
}
}

21. Merge Two Sorted Lists

easy

Example :

img

1
2
Input: list1 = [1,2,4], list2 = [1,3,4]
Output: [1,1,2,3,4,4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0);
ListNode handler = head; // head不动 handler动
while(l1 != null && l2 != null) {
if (l1.val <= l2.val) {
handler.next = l1;
l1 = l1.next;
} else {
handler.next = l2;
l2 = l2.next;
}
handler = handler.next;
}

if (l1 != null) {
handler.next = l1;
} else if (l2 != null) {
handler.next = l2;
}

return head.next;
}
}

19. Remove Nth Node From End of List

Example :

img

1
2
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Coding:

my method:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {

ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode count = dummy;
int m = 0;
// caculate the length of the list
while(count.next != null){
count = count.next;
m++;
}
if(m == 1){
//the lostnode only has one element
head = null;
return head;
}
// get to the note which is right before the one that is going to be deleted
ListNode delete = dummy;
for( int i = 0 ; i < m - n ; i ++){
delete = delete.next;
}
//delete the last element
if( n == 1 ){
delete.next = null;
}
// delete the first element
else if( n == m){
return head.next;
}
//delete the element in between
else {
delete.next = delete.next.next;
}
return head;

}
}

//!!!!!!!!!!!!!!!!!!second try!!!!!!!!!!!!!!!!!!!!!!!

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1, head);
ListNode left = dummy;
ListNode right = left;
for(int i = 0 ; i < n ; i ++){
right = right.next;
}
while(right.next != null){
right = right.next;
left = left.next;
}
if(left.next.next != null){ //其实可以不用考虑这个情况,因为n>=1
left.next = left.next.next;
}else{
left.next = null;
}
return dummy.next;
}
}

Improvement: don’t need to consider the start and the end of the linked list.

  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图: img
  • fast和slow同时移动,直到fast指向末尾,如题: img
  • 删除slow指向的下一个节点,如图: img
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;

ListNode slow = dummy;
ListNode fast = dummy;
for(int i = 0; i < n; i++){ // notice, here's i<n not i<n+t 画图就知道了
fast = fast.next;
}
while( fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next; // if write return head , it's wrong (head = [1], 1 can't pass)

}
}

160. Intersection of Two Linked Lists

Example :

img

1
2
3
4
5
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
Output: Intersected at '8'
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,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B (2nd node in A and 3rd node in B) are different node references. In other words, they point to two different locations in memory, while the nodes with value 8 in A and B (3rd node in A and 4th node in B) point to the same location in memory.
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// length of A
ListNode curA = new ListNode();
curA.next = headA;
int lenA = 0;
while( curA.next != null){
curA = curA.next;
lenA++;
}
// length of B
ListNode curB = new ListNode();
curB.next = headB;
int lenB = 0;
while( curB.next != null){
curB = curB.next;
lenB++;
}
// swap A and B if a.len < b.len
if(lenA < lenB){
int temp;
temp = lenA;
lenA = lenB;
lenB = temp;
curA = headB;
curB = headA;
}else{
curA = headA;
curB = headB;
}
// length gap
int gap = lenA - lenB;
// make cur A and B at the same place of the list
while(gap != 0){
curA = curA.next;
gap--;
}
// find the same element
while(curA != null){
if(curA == curB){ // it's curA == curB NOT curA.val == curB.val
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null; //!!!!!!!!!!!!!! not new ListNode(null);
}
}



//second try:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode dummyA = new ListNode(-1);
dummyA.next = headA;
ListNode dummyB = new ListNode(-1);
dummyB.next = headB;
ListNode tempA = dummyA;
ListNode tempB = dummyB;
int A = 0;
int B = 0;
while(tempA != null){
tempA = tempA.next;
A++;
}
while(tempB != null){
tempB = tempB.next;
B++;
}
if(A > B){ //这里错了!!!!!!!!!!!!!!!!!!!!!!!!!
ListNode temp = headA;
headA = headB;
headB =temp;
}
int gap = B - A;

while(gap > 0){
headB = headB.next;
gap--;
}

while(headA != null ){
if(headA == headB){
return headA;
}else{
headA = headA.next;
headB = headB.next;
}

}
return null;

}
}



142. Linked List Cycle II

Example :

img

1
2
3
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.

https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.md

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

img

x = z, 从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

Coding:

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.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
// here need to check if fast and fast.next is null, can't check if fast == slow directly cause there are cases without loops so fast can never equal to slow
while(fast != null && fast.next != null){ // find where fast and slow meet
fast = fast.next.next;
slow = slow.next;
if(fast == slow){ // there's a cycle
ListNode node1 = head;
ListNode node2 = fast;
while(node1 != node2 ){ // 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口(x = z)
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
}
return null;
}
}

109. Convert Sorted List to Binary Search Tree

Medium

Given the head of a singly linked list where elements are sorted in ascending order, convert it to a

*height-balanced*

binary search tree.

Example 1:

img

1
2
3
Input: head = [-10,-3,0,5,9]
Output: [0,-3,9,-10,null,5]
Explanation: One possible answer is [0,-3,9,-10,null,5], which represents the shown height balanced BST.
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
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head==null)
return null;
if(head.next==null)
return new TreeNode(head.val);
ListNode slow = head;
ListNode fast = head;
ListNode prev = null;
// Find the middle node and its predecessor
while (fast != null && fast.next != null) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}

// Disconnect the left and right parts of the list
if (prev != null) {
prev.next = null;
}

ListNode mid = slow;
TreeNode node = new TreeNode(mid.val);
node.right = sortedListToBST(mid.next);
node.left = sortedListToBST(head);
return node;

}
}