-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy path06-inplace-reversal-linked-list.rb
221 lines (193 loc) · 4.07 KB
/
06-inplace-reversal-linked-list.rb
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
class ListNode < Struct.new(:val, :next)
def to_s
node = self
str = ""
while node
str << "#{node.val} -> "
node = node.next
end
str << "NULL\n"
end
end
puts "Reverse linked list"
def reverse_list(head)
prev = nil
while head
nxt = head.next
head.next = prev
prev = head
head = nxt
end
prev
end
puts "Reverse linked list from P to Q"
def reverse_list_between(head, first, last)
dummy_head = ListNode.new(0, head)
head = dummy_head
while head.next && head.next.val != first
head = head.next
end
if head.next
tail = head.next
while tail && tail.val != last
tail = tail.next
end
prev = nil
if tail
prev = tail.next
tail.next = nil
end
match_head = head.next
while match_head
nxt = match_head.next
match_head.next = prev
prev = match_head
match_head = nxt
end
head.next = prev
end
dummy_head.next
end
head = ListNode.new(1)
tail = 2.upto(5).reduce(head) do |head, num|
head.next = ListNode.new(num)
end
puts reverse_list_between(head, 2, 4)
puts "Reverse every k element sublist"
def reverse_every_k_sublist(head, k)
return head if head.nil? || k == 1
tail, count = head, 1
while tail.next && count < k
tail = tail.next
count += 1
end
rem = tail.next
tail.next = nil
prev = reverse_every_k_sublist(rem, k)
while head
nxt = head.next
head.next = prev
prev = head
head = nxt
end
prev
end
def reverse_every_k_sublist(head, k)
return head if head.nil? || k == 1
tail, count = head, 1
prev_tail = dummy_head = ListNode.new(0, head)
while tail
nxt_tail = tail.next
if count % k == 0 || tail.next.nil?
tail.next = nil
prev_tail.next = tail
prev_tail = head
prev, cur = nil, head
while cur
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
end
head = nxt_tail
end
tail = nxt_tail
count += 1
end
dummy_head.next
end
head = ListNode.new(1)
tail = 2.upto(5).reduce(head) do |head, num|
head.next = ListNode.new(num)
end
puts reverse_every_k_sublist(head, 2)
puts "Reverse every alternating k elements"
def reverse_alternating_k(head, k)
return head if head.nil? || k <= 1
kth_tail, count = head, 1
while kth_tail.next && count < k
kth_tail = kth_tail.next
count += 1
end
prev = nxt_kth_tail = kth_tail.next
kth_tail.next = nil
if nxt_kth_tail
count = 1
while nxt_kth_tail.next && count < k
nxt_kth_tail = nxt_kth_tail.next
count += 1
end
nxt_kth_tail.next = reverse_alternating_k(nxt_kth_tail.next, k)
end
while head
nxt = head.next
head.next = prev
prev = head
head = nxt
end
prev
end
head = ListNode.new(1)
tail = 2.upto(9).reduce(head) do |head, num|
head.next = ListNode.new(num)
end
puts reverse_alternating_k(head, 2)
def reverse_alternating_k(head, k)
return head if k <= 1 || head.nil?
prev_tail, cur, cur_head, count = nil, head, head, 1
while cur
if count == k || cur.next.nil? && count < k
if prev_tail
prev_tail.next = cur
else
head = cur
end
prev = cur.next
cur.next = nil
cur = cur_head
while cur_head
nxt = cur_head.next
cur_head.next = prev
prev = cur_head
cur_head = nxt
end
elsif count == 2 * k
prev_tail = cur
count = 0
cur_head = cur.next
end
cur = cur.next
count += 1
end
head
end
head = ListNode.new(1)
tail = 2.upto(9).reduce(head) do |head, num|
head.next = ListNode.new(num)
end
puts reverse_alternating_k(head, 2)
puts "Rotate Linked list by number k"
def rotate(head, k)
return head if head.nil? || k <= 0
len, tail = 1, head
while tail.next
len += 1
tail = tail.next
end
k = k % len
return head if k.zero?
tail.next = head
k = len - k
while k > 1
head = head.next
k -= 1
end
new_head = head.next
head.next = nil
new_head
end
head = ListNode.new(1)
tail = 2.upto(5).reduce(head) do |head, num|
head.next = ListNode.new(num)
end
puts rotate head, 1