Leetcode.com problem 25: "Reverse Nodes in k-Group"

James S. Plank

Fri Aug 12 23:21:31 EDT 2022

Leetcode has a lot of linked-list practice questions, which can be nice when you're learning how to implement linked data structures, like in COSC202. I know I don't teach singly linked lists like this in COSC202, but you should be able to do this problem by thinking about the pointers. Even if you find Leetcode's definition of the ListNode to be confusing, you'll benefit from doing this problem.

Testing

It's really easy with Leetcode to get lazy and only test their examples. Especially with these pointer questions where it's a pain simply writing the testing code. I'm going to help you resist that temptation -- here's a main() that you can use for testing (basically, I'm creating the list like a queue from COSC202):

int main()
{
  ListNode *r, *l, *nn;
  int n, k;
  Solution s;

  cin >> k;                   // Read k first, and then read the nodes of the list.

  r = NULL;                   // I'm keeping track of the last node, so I can create
  while (cin >> n) {          // this list in order.  I always add the new node as
    nn = new ListNode(n);     // the next field of the last node I created.
    if (r == NULL) {
      r = nn;
      l = nn;
    } else {
      l->next = nn;
      l = nn;
    }
  }

  r = s.reverseKGroup(r, k);         // Call the method.

  for (l = r; l != NULL; l = l->next) {   // And print out the resulting list.
    printf("%d ", l->val);
  }
  printf("\n");
  return 0;
}

UNIX> echo 3    1 2 3 4 5 6 7 8 | ./a.out
3 2 1 6 5 4 7 8 
UNIX> echo 2    1 2 3 4 5 6 7 8 | ./a.out            # This one will seg fault if you're not careful,
2 1 4 3 6 5 8 7                                      # so make sure you test it.
UNIX> 

Organizing your solution

When I solved this one, I resisted the temptation to get cute. For example, I could have done the reversing while counting the nodes. I think that's a recipe for disaster. Instead, I started by counting the first k nodes. Obviously, if there aren't k nodes, you return head. Oh, and if k is one, you can return head also. After counting, I set a pointer called after_k to be the k-th node after head. You'll note, this could be NULL. I'm going to draw an example, with k equal to 3 and the list having the nodes 1 through 8 in order. Here's what my variables look like after I set after_k:

Now, I recursively call reverseKGroup() on after_k. When I'm done, I store the return value into a new pointer called rest. In this example, it will reverse the 4-5-6, and return a pointer to 6. You'll note, that after_k is still pointing to the 4. Here's the picture:

Now, I'm ready to reverse the three nodes starting at head. What I do is use three more pointers: prev, l and next. I set them to head, head->next and head->next->next respectively. Since k is at least two, these will all exist (although next may be NULL if k is two and the list has only two elements):

I switch l->next so it points to prev, and then I move prev, l and next to be the next nodes:

I repeat the previous steps (they're in a loop):

Now, you'll note that l equals after_k. This means you can exit your loop. Your last two steps are setting head to point to rest, and then you'll return prev:

Before you go coding and submitting, you should work through yourself what happens when after_k points to NULL. You'll have to check that case when you're setting next in the loop above, to avoid a seg-fault (I know from experience...).


Regardless, this is a great exercise in pointers and linked lists, and in my opinion is worth the effort that it takes to code it up and get it right!