方法 1)
首先反转整个队列(不考虑 21,22 等的相等性),然后使用堆栈反转每个单独的块(即 21,22 等)。这可以迭代地完成。
这类似于句子问题(著名的面试问题)中的反向词。
(请参阅下面的示例和伪代码)
方法2)
如果您绝对想进行递归,那么我建议您使用队列作为辅助存储,而不是堆栈。
您将一个块排入辅助队列,递归地反转列表的其余部分,然后将元素重新排入主队列。
代码将是这样的(handwavy 伪)
StrangeReverse(Queue <T> q) {
Queue<T> aux;
// this removes first block from q, and places them in aux
while (elem_of_first_block(q)) {
aux.Enque(elem);
}
// Recursively reverse the rest of the q.
StrangeReverse(q);
// place the first block back in q, at the end.
// in the order they appeared originally.
while (aux.HasElements()) {
q.Enque(aux.Deque());
}
}
递归版本可以通过队列堆栈转换为迭代!您从每个块中创建一个队列,并将它们堆叠起来。然后弹出堆栈,使用队列。
方法 1 的示例
[11, 12, 21, 22, 43, 44]
反转这个(使用堆栈或递归方法)
[44, 43, 22, 21, 12, 11]
现在反转每个块:
push 44, the 43.
Stack = [44, 43]. Queue = [22, 21, 12, 11]
现在通过从堆栈中弹出来入队
Stack = [], Queue = [22, 21, 12, 11, 43, 44]
push 22, 21
Stack = [22, 21], Queue = [12, 11, 43, 44]
通过弹出堆栈来入队。
Stack = [], Queue = [12, 11, 43, 44, 21, 22]
最后我们得到
[43, 44, 21, 22, 11, 12]
注意:要确定一个块,您可能需要在队列上使用 peek 方法。
方法一的伪代码
void StrangeReverse(Queue<T> q) {
Stack<T> s;
int count = q.Count();
if (count < 2) return;
for (i = 0; i < count; i++) {
T elem = q.Deque();
s.Push(elem);
}
while (s.HasElements()) {
T elem = s.Pop();
q.Enque(elem);
}
// Now the queue has been reversed,
// in the normal fashion.
ReverseBlocks(q);
}
void ReverseBlocks(Queue<T> q) {
int reversed = 0;
int count = q.Count();
while (reversed < count) {
reversed += ReverseSingleBlock(q);
}
}
int ReverseSingleBlock(Queue <T> q) {
Stack <T> s;
T prevElem = q.Deque();
s.Push(prevElem);
T curElem = q.Peek();
while(curElem == prevElem) {
s.Push(curElem);
q.Deque();
prevElem = curElem;
curElem = q.Peek();
}
int count = 0;
while(s.HasElements()) {
T elem = s.Pop();
q.Enque(elem);
count++;
}
return count;
}