CodeGround
DashboardProblemsInterviewsAssessmentsCourses
CodeGround
DashboardProblemsInterviewsAssessmentsCourses
The Technical Interview Course

0 of 170 lessons complete

  • Changing links without losing the list
  • The dummy head
  • Two pointers at different speeds
  • A fixed gap between two pointers
  • Composing three things you already have
  • Mapping old nodes to new ones
  • Walking two lists at once with a carry
  • When an array is secretly a linked list
  • A hash map over a doubly linked list
  • Merging many by merging two, repeatedly
  • Reversing in fixed groups
  • Retrieval: the four habits

Linked Lists

66 / 170

Linked Lists/Lesson 11 of 12ยทAbout 59 min

Reversing in fixed groups

The hardest pointer surgery in the set. Everything you need is already written; the difficulty is bookkeeping.

The task

Reverse the list in consecutive groups of k nodes. If fewer than k nodes remain at the end, leave them alone.

You can already reverse a whole list. Two things are new: reversing only a segment, and reconnecting each reversed segment to the ones on either side.

Why it works

Check the length before touching anything

The rule about leaving a short tail alone means you must know whether k nodes remain before you start reversing. Reversing first and undoing it is possible and horrible.

So each round begins by walking k nodes ahead to confirm they exist. If they do not, the loop stops and the remainder stays as it is. That walk is O(k) per group and O(n) overall, so it costs nothing asymptotically.

1class Node:2    def __init__(self, val, next=None):3        self.val, self.next = val, next4 5def build(values):6    head = None7    for value in reversed(values):8        head = Node(value, head)9    return head10 11def to_list(node):12    out = []13    while node:14        out.append(node.val)15        node = node.next16    return out17 18def has_k_more(node, k):19    while k > 0 and node:20        node = node.next21        k -= 122    return k == 023 24head = build([1, 2, 3, 4, 5])25print(has_k_more(head, 3), has_k_more(head, 5), has_k_more(head, 6))

Why it works

Name the four things you need

For each group, four references matter and losing any one of them is fatal.

The node before the group, which will need to point at the group's new first node. The group's original first node, which becomes its last and must point at whatever follows. The group's original last node, which becomes its first. And the node after the group, which is where the next round begins.

Write those four down as named variables before writing any assignment. The surgery is short once they exist and impossible to keep straight without them.

Reversing exactly k nodes

Segment reversal is the ordinary reversal loop with a counter instead of a None check, and it returns both ends of what it reversed.

1class Node:2    def __init__(self, val, next=None):3        self.val, self.next = val, next4 5def build(values):6    head = None7    for value in reversed(values):8        head = Node(value, head)9    return head10 11def to_list(node):12    out = []13    while node:14        out.append(node.val)15        node = node.next16    return out17 18def reverse_k(head, k):19    """Reverse exactly k nodes. Return (new_head, new_tail, rest)."""20    prev, curr = None, head21    for _ in range(k):22        ahead = curr.next23        curr.next = prev24        prev = curr25        curr = ahead26    return prev, head, curr        # head became the tail27 28new_head, new_tail, rest = reverse_k(build([1, 2, 3, 4, 5]), 3)29print(to_list(new_head), new_tail.val, to_list(rest))

Tip

The tail is left dangling on purpose

After reversing, new_tail.next still points at prev from the loop's perspective, which is why printing new_head stops after three values. The reversed segment is properly terminated.

The caller is responsible for attaching new_tail.next to whatever comes next, which is either the next reversed group or the untouched remainder. Returning all three references is what makes that possible.

Key idea

A dummy head, one last time

The first group's predecessor does not exist, since the group starts at the head. A dummy node before the list supplies one, and the answer is dummy.next as always.

This is the last of the five problems in this unit where the dummy head removes a special case. If you take one habit from this unit, take that one.

How to approach this

Write has_k_more and reverse_k as separate functions and test them on their own. Then the main loop is: while another full group exists, reverse it, stitch it in, and advance the predecessor to the group's new tail.

Attempting it as one function with five pointers is how this problem eats an hour. It is not conceptually hard; it is unforgiving.

Predict the outputยท 5 min

Predict the output: attaching the front but not the back

One group of three is reversed and stitched to the front, and then the list is printed. The 4 and the 5 were deliberately left untouched. Type exactly what it prints.

Python
1class Node:2    def __init__(self, val, next=None):3        self.val, self.next = val, next4 5def build(values):6    head = None7    for value in reversed(values):8        head = Node(value, head)9    return head10 11def to_list(node):12    out = []13    while node:14        out.append(node.val)15        node = node.next16    return out17 18def build(values):19    head = None20    for value in reversed(values):21        head = Node(value, head)22    return head23 24def to_list(node):25    out = []26    while node:27        out.append(node.val)28        node = node.next29    return out30 31def reverse_k(head, k):32    prev, curr = None, head33    for _ in range(k):34        ahead = curr.next35        curr.next = prev36        prev = curr37        curr = ahead38    return prev, head, curr39 40dummy = Node(0, build([1, 2, 3, 4, 5]))41new_head, new_tail, rest = reverse_k(dummy.next, 3)42dummy.next = new_head                 # front attached43print(to_list(dummy.next))
Problemยท 40 min

Reverse Nodes In K Group

Read the constraints first and let them tell you what complexity is expected. Derive the approach, implement it, run the tests, and submit when it passes.

PreviousMerging many by merging two, repeatedly
NextRetrieval: the four habits

0 of 3 parts complete