【力扣roadmap】1172. 餐盘栈

22 阅读1分钟

题目描述

image.png

思路

这题目叫做无限栈来得更好一点。 就纯模拟:

  • push的时候从左向右看第一个未满的,push进去;

  • pop的时候,从右向左看,第一个有元素的,pop出来

代码

class DinnerPlates:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.not_full_index = SortedSet() # 存放未满栈的下标(可能有空栈在其中)
        self.top_index = 0 # 指向右侧第一个空栈(随着push增大,随着pop而缩小)
        self.infinity_stk = [] # 模拟无限栈

    def push(self, val: int) -> None:  # 从左向右查看第一个未满的栈
        if len(self.not_full_index) == 0 :  # 说明添加刚刚开始或者目前全满
            self.infinity_stk.append([]) # 末尾放一个空列表
            self.infinity_stk[self.top_index].append(val) # push操作
            if self.capacity > 1 : # 如果cap为1  一上来就填满了 未满set不会纳入top_index; 否则纳入top_index
                self.not_full_index.add(self.top_index)
            self.top_index += 1 # 继续指向下一个空栈位置
        else :
            first_not_full = self.not_full_index[0] # 得到第一个未空栈
            self.infinity_stk[first_not_full].append(val) # push
            if len(self.infinity_stk[first_not_full]) == self.capacity : # 这个栈满了
                self.not_full_index.remove(first_not_full)  # 将这个栈移除未满set
        
    def pop(self) -> int:  # 从右向左查看
        while self.top_index > 0 and len(self.infinity_stk[self.top_index-1]) == 0 : # top_index此时未必指向右侧第一个空栈,因为popAtStack可能把中间stk弹空了
            self.not_full_index.remove(self.top_index-1)  # 空栈不在未满set的考虑范围内
            self.top_index -= 1  # 左移top_index
        if self.top_index == 0 : # 无限栈没有任何元素
            return -1 
        ret = self.infinity_stk[self.top_index-1].pop() # 右侧第一个有元素的栈self.top_index - 1 
        self.not_full_index.add(self.top_index-1) # 此时self.top_index-1必为未满,可能为空
        return ret 
        
    def popAtStack(self, index: int) -> int:
        if index >= len(self.infinity_stk) or index < 0 :  # invalid case 
            return -1 
        
        stk = self.infinity_stk[index] 

        if not stk and len(stk) == 0 : # invalid case 
            return -1 
        ret = stk.pop() 
        self.not_full_index.add(index) # 此时index必为一个未满栈,可能为空
        return ret 



# Your DinnerPlates object will be instantiated and called as such:
# obj = DinnerPlates(capacity)
# obj.push(val)
# param_2 = obj.pop()
# param_3 = obj.popAtStack(index)