题目
原文:
Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in real life, we would likely start a new stack when the previous stack exceeds some threshold. Implement a data structure SetOfStacks that mimics this. SetOfStacks should be composed of several stacks, and should create a new stack once the previous one exceeds capacity. SetOfStacks.push() and SetOfStacks.pop() should behave identically to a single stack (that is, pop() should return the same values as it would if there were just a single stack).
FOLLOW UP
Implement a function popAt(int index) which performs a pop operation on a specific sub-stack.
译文:
想象一下,一 堆盘子,如果堆得太高,它很可能会倒,因此在现实生活中,如果盘子堆到一定高度,我们就会重新起一个堆。现在实现一个新的数据结构SetOfStack来模拟这样现象。SetOfStack当中包含很多的堆栈,当一个堆栈达到上限的时候,启用下一个堆栈。SetOfStack.push 和 SetOfStack.pop应该和普通堆栈的操作一样。
进阶:
实现一个函数popAt(int index),指定在哪个堆栈上弹出元素。
解答
以下是书本的解答
由于要和普通的堆栈的push()有相同的效果,也就是说每次push()都必须将元素放到最近使用的一个堆栈中。但是在这个堆栈已经满了情况下,那就必须建一个新的堆栈然后再入栈。那么push的实现如下:
public void push(int v) { Stack last = getLastStack(); if (last != null && !last.isAtCapacity()) { // add to last stack last.push(v); } else { // must create new stack Stack stack = new Stack(capacity); stack.push(v); stacks.add(stack); } }
public int pop() { Stack last = getLastStack(); System.out.println(stacks.size()); int v = last.pop(); if (last.size == 0) stacks.remove(stacks.size() - 1); return v; }
class SetOfStacks { ArrayList<Stack> stacks = new ArrayList<Stack>(); public int capacity; //容量 public SetOfStacks(int capacity) { this.capacity = capacity; } public Stack getLastStack() { if (stacks.size() == 0) return null; return stacks.get(stacks.size() - 1); } public void push(int v) { Stack last = getLastStack(); if (last != null && !last.isAtCapacity()) { // add to last stack last.push(v); } else { // must create new stack Stack stack = new Stack(capacity); stack.push(v); stacks.add(stack); } } public int pop() { Stack last = getLastStack(); System.out.println(stacks.size()); int v = last.pop(); if (last.size == 0) stacks.remove(stacks.size() - 1); return v; } public int popAt(int index) { return leftShift(index, true); } public int leftShift(int index, boolean removeTop) { Stack stack = stacks.get(index); int removed_item; if (removeTop) removed_item = stack.pop(); else removed_item = stack.removeBottom(); if (stack.isEmpty()) { stacks.remove(index); } else if (stacks.size() > index + 1) { int v = leftShift(index + 1, false); stack.push(v); } return removed_item; } } class Stack { private int capacity; public Node top, bottom; public int size = 0; public Stack(int capacity) { this.capacity = capacity; } public boolean isAtCapacity() { return capacity == size; } public void join(Node above, Node below) { if (below != null) below.above = above; if (above != null) above.below = below; } public boolean push(int v) { if (size >= capacity) return false; size++; Node n = new Node(v); if (size == 1) bottom = n; join(n, top); top = n; return true; } public int pop() { Node t = top; top = top.below; size--; return t.value; } public boolean isEmpty() { return size == 0; } public int removeBottom() { Node b = bottom; bottom = bottom.above; if (bottom != null) bottom.below = null; size--; return b.value; } }