Cracking the coding interview--Q3.3

本文探讨了一个数据结构SetOfStacks的设计,它能够动态地创建多个堆栈,当一个堆栈达到预设容量时,会自动创建新的堆栈。同时,实现了在特定堆栈上执行弹出操作的功能。此结构旨在提高资源利用效率,通过在不同堆栈间灵活分配元素,优化内存管理和性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

原文:

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);
		}
	}

那pop()如何实现呢?和push()差不多,也一定要在最近的一个堆栈上操作。但是如果最后一个堆栈是空的话,就应该将其移除。

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;
    }

那进阶的问题这么处理呢?
这个问题确实有点难度。实现起来也比较麻烦,因为整个系统看起来应该像一个“翻转”系统。如果我从堆栈1中弹出一个元素,那么我们需要将堆栈2底部的元素压到堆栈1的顶端。堆栈3的元素要到堆栈2....
注:你可能会不同意我的说法。认为实现这个函数不需要“翻转”整个堆栈。系统中的每个堆栈并不需要都是满栈的,这样的话也可以省下很多的时间复杂度,特别是在堆栈非常大的时候。但是如果假设除了最后一个堆栈之外,所有的堆栈必须满栈的话,这样的方法就不行了。具体采用什么样的结构,你可以在面试时和面试官好好沟通然后决定。

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;
    }
}

--- EOF---


基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。 智能教学辅助系统 这是一个智能教学辅助系统的前端项目,基于 Vue3+TypeScript 开发,使用 Ant Design Vue 作为 UI 组件库。 功能模块 用户模块 登录/注册功能,支持学生和教师角色 毛玻璃效果的登录界面 教师模块 备课与设计:根据课程大纲自动设计教学内容 考核内容生成:自动生成多样化考核题目及参考答案 学情数据分析:自动化检测学生答案,提供数据分析 学生模块 在线学习助手:结合教学内容解答问题 实时练习评测助手:生成随练题目并纠错 管理模块 用户管理:管理员/教师/学生等用户基本管理 课件资源管理:按学科列表管理教师备课资源 大屏概览:使用统计、效率指数、学习效果等 技术栈 Vue3 TypeScript Pinia 状态管理 Ant Design Vue 组件库 Axios 请求库 ByteMD 编辑器 ECharts 图表库 Monaco 编辑器 双主题支持(专业科技风/暗黑风) 开发指南 # 安装依赖 npm install # 启动开发服务器 npm run dev # 构建生产版本 npm run build 简介 本项目旨在开发一个基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值