面试题 03.03. 堆盘子

面试题 03.03. 堆盘子 #

题目 #

堆盘子。设想有一堆盘子,堆太高可能会倒下来。因此,在现实生活中,盘子堆到一定高度时,就会堆另外一堆盘子。实现数据结构 SetOfStacks,模拟这种行为。SetOfStacks 应该由多个栈组成,并在在前一个栈填满时新建一个栈。此外,SetOfStacks.push()SetOfStacks.pop() 应该与普通栈的操作方法相同 (即,pop 的返回值应该与只有一个栈时的情况一致)。此外,实现 popAt(int index) 方法,根据指定的子栈,执行 pop 操作。

当某个栈为空时,应删除该栈。当栈中没有元素或不存在该栈时,poppopAt 应返回 -1

思路 #

代码 #

class StackOfPlates {
    private class stackNode {
        public int val;
        public stackNode next;
        
        stackNode(int val, stackNode next) {
            this.val = val;
            this.next = next;
        }
    }
    
    private class Stack {
        private int size;
        private int capacity;
        private stackNode sentinel;
        
        Stack(int capacity) {
            this.size = 0;
            this.capacity = capacity;
            this.sentinel = new StackNode(-1, null);
        }
        
        public void push (int val) {
            this.sentinel.next = new stackNode(val, this.sentinel.next);
            this.size += 1;
        }
        
        public int pop() {
            int result = this.sentinel.next.val;
            this.sentinel.next = this.sentinel.next.next;
            this.size -= 1;
            return result;
        }
        
        public boolean isEmpty() {
            return this.size == 0;
        }
        
        public boolean isFull() {
            return this.size == this.capacity;
        }
    }
    
    private class ListNode {
        Stack stack;
        ListNode prev;
        ListNode next;
        
        ListNode(int capacity, ListNode prev, ListNode next) {
            this.stack = new Stack(capacity);
            this.prev = prev;
            this.next = next;
        }
    }
    
    private ListNode sentinel;
    private int capacity;
    
    public StackOfPlates(int cap) {
        this.sentinel = new ListNode(cap, null, null);
        this.sentinel.prev = this.sentinel.next = this.sentinel;
        
        this.capacity = cap;
    }
    
    public void push(int val) {
        if (this.capacity == 0) return;
        
        if (this.isEmpty() == true || this.sentinel.prev.stack.isFull() == true) {
            this.sentinel.prev = new ListNode(this.capacity, this.sentinel.prev, this.sentinel);
            this.sentinel.prev.prev.next = this.sentinel.prev;
        }
        
        this.sentinel.prev.stack.push(val);
    }
    
    public int pop() {
        if (this.isEmpty() == true) return -1;
        
        int result = this.sentinel.prev.stack.pop();
        if (this.sentinel.prev.stack.isEmpty() == true) delete(this.sentinel.prev);
        
        return result;
    }
    
    public int popAt(int index) {
        if (this.isEmpty() == true) return -1;
        
        ListNode ptr = this.sentinel.next;
        for(int i=0; i<index; i++) {
            ptr = ptr.next;
            if (ptr == this.sentinel) return -1;
        }
        
        int result = ptr.stack.pop();
        if (ptr.stack.isEmpty() == true) delete(ptr);
        
        return result;
    }
    
    public boolean isEmpty() {
        return this.sentinel.prev == this.sentinel;
    }
    
    public void delete(ListNode ptr) {
        ptr.prev.next = ptr.next;
        ptr.next.prev = ptr.prev;
    }
}