forked from fishercoder1534/Leetcode
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path_25.java
140 lines (127 loc) · 4.55 KB
/
_25.java
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package com.fishercoder.solutions;
import com.fishercoder.common.classes.ListNode;
public class _25 {
/**
* We use recursion to go all the way until the end: when the number of nodes are smaller than k;
* then we start to reverse each group of k nodes from the end towards the start.
*/
public static class Solution1 {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode curr = head;
int count = 0;
while (curr != null && count != k) {
//find the k+1 node
curr = curr.next;
count++;
}
if (count == k) {
/**after this below recursive call finishes, it'll return head;
* then this returned "head" will become "curr", while the head
* in its previous callstack is the real head after this call.
* Setting up a break point will make all of this crystal clear.*/
curr = reverseKGroup(curr, k);
while (count-- > 0) {
ListNode temp = head.next;
head.next = curr;
curr = head;
head = temp;
}
head = curr;
}
return head;//we run out of nodes before we hit count == k, so we'll just directly return head in this case as well
}
}
public static class Solution2 {
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null || head.next == null || k == 1) {
return head;
}
int n = 0; // number of nodes
ListNode curr = head;
while (curr != null) {
n++;
curr = curr.next;
}
ListNode prev = null;
ListNode next = null;
ListNode newHead = null;
ListNode tail1 = null;
ListNode tail2 = head;
curr = head;
while (n >= k) {
// reverse nodes in blocks of k
for (int i = 0; i < k; i++) {
// linked List reversal code
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
if (newHead == null) {
newHead = prev;
}
if (tail1 != null) {
tail1.next = prev;
}
tail2.next = curr; // when n is not multiple of k
tail1 = tail2;
tail2 = curr;
prev = null;
n -= k;
}
return newHead;
}
}
public static class Solution3 {
/**
* My completely original solution on 10/25/2021. Beats 100% submissions on LeetCode in runtime.
* Again, using a pen and paper to visualize the process helps a lot!
* My helper function returns two nodes: reversed node head and the starting node for the next reversal.
*/
public ListNode reverseKGroup(ListNode head, int k) {
ListNode pre = new ListNode(-1);
pre.next = head;
ListNode tmp = pre;
ListNode curr = head;
ListNode[] result = new ListNode[]{null, curr};
do {
result = reverseKGroupHelper(result[1], k);
if (result[0] == result[1]) {
tmp.next = result[0];
return pre.next;
} else {
tmp.next = result[0];
while (tmp.next != null) {
tmp = tmp.next;
}
}
} while (true);
}
private ListNode[] reverseKGroupHelper(ListNode head, int k) {
int originalK = k;
ListNode tmp = head;
while (tmp != null) {
tmp = tmp.next;
k--;
}
if (k > 0) {
return new ListNode[]{head, head};
} else {
tmp = head;
k = originalK;
ListNode prev = null;
while (tmp != null) {
ListNode next = tmp.next;
tmp.next = prev;
prev = tmp;
tmp = next;
k--;
if (k == 0) {
return new ListNode[]{prev, tmp};
}
}
return null;
}
}
}
}