Reverse Every K Nodes Of A Linked List
August 26, 2011
Here is another from our collection of interview questions:
Given a list of elements and a block size k, return the list of elements with every block of k elements reversed, starting from the beginning of the list. For instance, given the list 1, 2, 3, 4, 5, 6 and the block size 2, the result is 2, 1, 4, 3, 6, 5.
Your task is to write a function to solve the sublist-reversal problem. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
In Clojure.
In Haskell:
import Data.List
revBlockwise n = concat
. unfoldr (\e -> case e of [] -> Nothing;x -> Just (reverse $ take n x,drop n x))
Here’s my clojure solution. More details at my blog.
Oops, posted the wrong version:
Python (please post a more elegant solution):
Using PLT Racket
Essentially the same as the take/drop version given except that split-at does both at the same time. I had to check against length instead of null? because split-at complained when given a list shorter than k.
Oops. I forgot to change let*-values back to let-values.
C++
Been playing with Haskell while waiting for C++ code to compile. Here is a solution I came up with.
sublists k [] = []
sublists k l = take k l : sublists k (drop k l)
reverseSublists k l = map reverse $ sublists k l
Everyone’s doing Haskell today. Here’s my take:
Solution in Java.
public static void reverseNodes(int blockSize, List list) {
int end;
char c;
for(int i = 0, start = 0; i list.size()) ? list.size() : i + blockSize) – 1;
while(start < end) {
c = list.get(start);
list.set(start++, list.get(end));
list.set(end–, c);
}
}
}
Two Python 3 solutions. One returns a new list, the other reverses the groups in-place.
The problem doesn’t specify what to do when the number of elements in the list is not a multiple of the group size. For example,
rev_groups([1,2,3,4,5], 3) -> ?
I chose to reverse the short group.
A ruby version (could not for the life of me find a one liner but would love to see one) …
# Ruby version
def reverse list, k
list.each_slice(k).collect{ |s| s.reverse }.flatten
end
reverse [1, 2, 3, 4, 5, 6], 2
That’s what I was looking for @Paul Mylchreest. Well done.
So many haskells!
reverseNodes :: Int -> [a] -> [a]
reverseNodes _ [] = []
reverseNodes n xs = (reverse $ take n xs) ++ reverseNodes n (drop n xs)
How about a Factor!
And, to use it:
JavaScript using nodejs:
/**
* Program that solve the sublist-reversal problem.
*
* @see https://programmingpraxis.com/2011/08/26/reverse-every-k-nodes-of-a-linked-list/
*/
var App = function() {
/**
* Reverse every sub-list from a given list.
* @param list A list of integers.
* @param size The size of the sub-list.
*/
this.reverse = function(list, size) {
// Validate input.
if (!list || !size || size <= 0) {
throw 'Illegal arguments';
}
var result = [];
for (var i = 0; i < list.length; i += size) {
var sub = list.slice(i, i + size).reverse();
for (var j = 0; j < sub.length; j++) {
result.push(sub[j]);
}
}
return result;
};
};
// Test.
var list = [1,2,3,4,5,6,7,8,9];
var size = 2;
var a = new App();
var result = a.reverse(list, size);
console.log(result);
JavaScript using nodejs:
Haskell
Go:
mm.. some are preceeding ^^
KRev.java
revk.go
Here’s a Python 3 version that works for any iterable. It is a generator that lazily evaluates groups of k items from the input iterable and yields the items in reverse order. The null argument should be set to a value that cannot appear in the input, and defaults to None.
Someone requested some one-liners.
Here a a couple in Python 3:
One line in python –
for y in [x[n:n+2] for n in range(0,len(x),2)]],[])
One line in python
Solution in C# for a singly linked list. Uses O(k) auxiliary space.