I recently encounter an algorithm problem:
Reverse a singly-linked list in blocks of k in place. An iterative approach is preferred. The first block of the resulting list should be maximal with regards to k. If the list contains n elements, the last block will either be full or contain n mod k elements.
For example:
k = 2, list = [1,2,3,4,5,6,7,8,9], the reversed list is [8,9,6,7,4,5,2,3,1]
k = 3, list = [1,2,3,4,5,6,7,8,9], the reversed list is [7,8,9,4,5,6,1,2,3]
My code is shown as below.
Is there an O(n) algorithm that doesn't use a stack or extra space?
public static ListNode reverse(ListNode list, int k) {
Stack<ListNode> stack = new Stack<ListNode>();
int listLen = getLen(list);
int firstBlockSize = listLen % k;
ListNode start = list;
if (firstBlockSize != 0) {
start = getBlock(stack, start, firstBlockSize);
}
int numBlock = (listLen) / k;
for (int i = 0; i < numBlock; i++) {
start = getBlock(stack, start, k);
}
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while (!stack.empty()) {
cur.next = stack.peek();
cur = stack.pop();
while (cur.next != null) {
cur = cur.next;
}
}
return dummy.next;
}
public static ListNode getBlock(Stack<ListNode> stack, ListNode start, int blockSize) {
ListNode end = start;
while (blockSize > 1) {
end = end.next;
blockSize--;
}
ListNode temp = end.next;
end.next = null;
stack.push(start);
return temp;
}
public static int getLen(ListNode list) {
ListNode iter = list;
int len = 0;
while (iter != null) {
len++;
iter = iter.next;
}
return len;
}