Skip to content

Commit 0cbbdda

Browse files
author
Zichao Wu
committed
Add linked list
1 parent 5b84551 commit 0cbbdda

File tree

2 files changed

+153
-1
lines changed

2 files changed

+153
-1
lines changed

linkedlist-merge/23. Merge k Sorted Lists.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# Definition for singly-linked list.
2+
from typing import List, Optional
3+
class ListNode:
4+
def __init__(self, val=0, next=None):
5+
self.val = val
6+
self.next = next
7+
18
import heapq
29
class Solution:
310
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
@@ -16,8 +23,63 @@ def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
1623
res.next = ListNode(topVal)
1724
res = res.next
1825

19-
nextNode = lists[i].next
26+
nextNode = lists[i].next
2027
if nextNode:
2128
heapq.heappush(h, (nextNode.val, i))
2229
lists[i] = nextNode
2330
return dummy.next
31+
32+
class Solution:
33+
def mergeTwo(self, head1, head2):
34+
dummy = ListNode(0)
35+
cur = dummy
36+
37+
# Iterate through both linked lists
38+
while head1 and head2:
39+
# Add the smaller node to the merged list
40+
if head1.val <= head2.val:
41+
cur.next = head1
42+
head1 = head1.next
43+
else:
44+
cur.next = head2
45+
head2 = head2.next
46+
cur = cur.next
47+
# If any list is left, append it to
48+
# the merged list
49+
if head1:
50+
cur.next = head1
51+
else:
52+
cur.next = head2
53+
54+
# Return the merged list starting
55+
# from the next of dummy node
56+
return dummy.next
57+
58+
"""
59+
Merge linked lists in array[i:j+1]
60+
Accepts:
61+
arr - array of linked list
62+
i - left index in arr, inclusive
63+
j - right index in arr, inclusive
64+
Returns - head of merged list
65+
"""
66+
def mergeListsRecur(self, i, j, arr):
67+
# If single linked list, return its head since it's sorted already
68+
if i == j:
69+
return arr[i]
70+
# Find the middle list
71+
mid = i + (j - i) // 2 # [0,1,2] being 1: merge(merge(0+1), 2)
72+
# [0,1,2,3] being merge(merge(0,1),merge(2,3))
73+
# Merge lists from i to mid
74+
head1 = self.mergeListsRecur(i, mid, arr)
75+
# Merge lists from mid+1 to j
76+
head2 = self.mergeListsRecur(mid + 1, j, arr)
77+
# Merge the above 2 lists
78+
head = self.mergeTwo(head1, head2)
79+
return head
80+
81+
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
82+
# Base case for 0 lists to merge
83+
if len(lists) == 0:
84+
return None
85+
return self.mergeListsRecur(0, len(lists) - 1, lists)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Definition for singly-linked list.
2+
from typing import Optional
3+
class ListNode:
4+
def __init__(self, val=0, next=None):
5+
self.val = val
6+
self.next = next
7+
8+
class Solution:
9+
# Reverse using Iteration
10+
# This solution iterates through the linked list in groups of k nodes,
11+
# reversing the links within each group.
12+
# It maintains a pointer to the new head of the reversed list and a tail pointer
13+
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
14+
if not head or k == 1:
15+
return head
16+
17+
curr = head
18+
newHead = None
19+
tail = None
20+
21+
while curr:
22+
oldGroupHead = curr
23+
prev = None
24+
nextNode = None
25+
count = 0
26+
27+
# Reverse the nodes in the current group
28+
while curr and count < k:
29+
nextNode = curr.next # store ptr to next node temporarily
30+
curr.next = prev # reverse the link
31+
prev = curr # forward prev ptr to cur node
32+
curr = nextNode # forward cur ptr to next node
33+
count += 1
34+
35+
# If newHead is null, set it to the
36+
# last node of the first group
37+
if not newHead:
38+
newHead = prev # will only assigned once per program
39+
40+
# Connect last group tail (1 and 3 in below example) to the
41+
# current reversed group head
42+
if tail:
43+
# precondition: prev points to the first node of current group we just reversed (4 or 5 in below example)
44+
# precondition: tail points to the last node of the reversed previous group (1 or 3 in below example)
45+
# precondition: curr points to the first node of the next group (5)
46+
# precondition: oldGroupHead points to the first node of current group pre-reversal (1 or 3 in below example)
47+
tail.next = prev # 2->1 => 4->3 => 5
48+
49+
# Move tail to the end of
50+
# the reversed group
51+
tail = oldGroupHead
52+
53+
return newHead
54+
55+
56+
# Reverse using Stack
57+
# This is an alternative solution using a stack to reverse the nodes in k-groups.
58+
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
59+
if not head or k == 1:
60+
return head
61+
62+
stack = []
63+
curr = head
64+
prev = None
65+
66+
while curr:
67+
68+
# Terminate the loop when either
69+
# current == None or count >= k
70+
count = 0
71+
while curr and count < k:
72+
stack.append(curr)
73+
curr = curr.next
74+
count += 1
75+
76+
# Now pop the elements from the stack one by one
77+
while stack:
78+
79+
# If the final list has not been started yet
80+
if not prev:
81+
prev = stack.pop()
82+
head = prev
83+
else:
84+
prev.next = stack.pop()
85+
prev = prev.next
86+
87+
# Set the next pointer of the last node to None
88+
prev.next = None
89+
90+
return head

0 commit comments

Comments
 (0)