Leetcode面T3(1-5)栈,带你搞懂Android启动速度优化

本文详细介绍了LeetCode面试中与栈相关的四道题目,包括栈的最小值、堆盘子、化栈为队以及栈排序问题,通过具体的Java实现解析了这些操作如何应用于Android启动速度优化。
摘要由CSDN通过智能技术生成

}

}

public int pop(int stackNum) {

int topVal = peek(stackNum);

if (size[stackNum] > 0)

size[stackNum] -= 1;

return topVal;

}

public int peek(int stackNum) {

if (size[stackNum] == 0)

return -1;

return arr[stackNum*stackSize+size[stackNum]-1];

}

public boolean isEmpty(int stackNum) {

return size[stackNum] == 0;

}

}

Q3.2 栈的最小值

请设计一个栈,除了常规栈支持的pop与push函数以外,还支持min函数,该函数返回栈元素中的最小值。执行push、pop和min操作的时间复杂度必须为O(1)。

示例:

MinStack minStack = new MinStack();

minStack.push(-2);

minStack.push(0);

minStack.push(-3);

minStack.getMin(); --> 返回 -3.

minStack.pop();

minStack.top(); --> 返回 0.

minStack.getMin(); --> 返回 -2.

思路:

利用一个min变量标记当前的最小栈内元素。压栈时,如果最小元素发生变更,就把当前最小元素也进行压栈,标记这一次的最小元素变更情况。出栈时,如果遇到当前最小值与栈顶元素相同的情况,就连着这个元素一起弹出,并将当前最小值更新为这个元素的下一个元素。理论上这个方式比双栈更省空间。

class MinStack {

/**

  • initialize your data structure here.

*/

Stack stack;

//将最小值初始化为整型的最大值

int min = Integer.MAX_VALUE;

public MinStack() {

//初始化一个栈

stack = new Stack();

}

public void push(int x) {

//当min==x时要重新存一下最小值,否则最小的值min会出现两次

//一次是当前的min,一次是维护当前min的第一个值

//如果if的条件改为min>x,则会影响pop()出栈的逻辑

if (min >= x) {

stack.push(min);

//维护最小值序列的第一个值(最小),并赋值给min

min = x;

}

//入栈

stack.push(x);

}

public void pop() {

//栈为空时返回空即可

if (stack.isEmpty()) {

return;

}

//长度为1时其实只存了min的初值,没有存其他值

if (stack.size() == 1) {

min = Integer.MAX_VALUE;

//min==top()说明栈顶元素是一段维护最小值序列的第一个值(即最小值)

} else if (min == top()) {

//先把这个最小值弹出

stack.pop();

//此时的栈顶元素是之前入栈时额外存入的最小值

min = top();

}

//出栈

stack.pop();

}

public int top() {

//此处直接调用java中与stack相关的API即可

return (int)stack.peek();

}

public int getMin() {

//min可以随时返回,达到了时间复杂度必须为O(1)的要求

return min;

}

}

/**

  • Your MinStack object will be instantiated and called as such:

  • MinStack obj = new MinStack();

  • obj.push(x);

  • obj.pop();

  • int param_3 = obj.top();

  • int param_4 = obj.getMin();

*/

Q3.3 堆盘子

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

示例1:

输入:

[“StackOfPlates”, “push”, “push”, “popAt”, “pop”, “pop”]

[[1], [1], [2], [1], [], []]

输出:

[null, null, null, 2, 1, -1]

示例2:

输入:

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

[“StackOfPlates”, “push”, “push”, “push”, “popAt”, “popAt”, “popAt”]

[[2], [1], [2], [3], [0], [0], [0]]

输出:

[null, null, null, null, 2, 1, 3]

class StackOfPlates {

//存储多个栈的容器

private List<Stack> stackList;

//盘子高度的最大值

private int cup;

public StackOfPlates(int cap) {

//构造函数完成初始化的功能

this.cup = cap;

stackList = new ArrayList<>();

}

public void push(int val) {

if (cup <= 0) {

return;

}

//这两个逻辑或的条件一定不能反过来写,只有栈不为空时才能有size==cup的判断

if (stackList.isEmpty() || stackList.get(stackList.size() - 1).size() == cup) {

//新建一个栈存入容器

Stack stack = new Stack();

stack.push(val);

stackList.add(stack);

return;

}

//栈未达到最大值就从容器中最后一个栈的末尾入栈

stackList.get(stackList.size() - 1).push(val);

}

public int pop() {

//直接调用已定义好的方法,下标参数为容器中最后一个栈的下标

return popAt(stackList.size() - 1);

}

public int popAt(int index) {

//下标越界

if (index < 0 || index >= stackList.size()) {

return -1;

}

//得到容器中下标对应的栈

Stack stack = stackList.get(index);

//栈为空

if (stack.isEmpty()) {

return -1;

}

//出栈

int res = stack.pop();

//栈为空时要把这个空栈删除

if (stack.isEmpty()) {

stackList.remove(index);

}

//将出栈的元素返回

return res;

}

}

/**

  • Your StackOfPlates object will be instantiated and called as such:

  • StackOfPlates obj = new StackOfPlates(cap);

  • obj.push(val);

  • int param_2 = obj.pop();

  • int param_3 = obj.popAt(index);

*/

Q3.4 化栈为队

实现一个MyQueue类,该类用两个栈来实现一个队列。

示例:

MyQueue queue = new MyQueue();

queue.push(1);

queue.push(2);

queue.peek();  // 返回 1

queue.pop();   // 返回 1

queue.empty(); // 返回 false

我们知道:同一段序列,分别存进一个栈和一个队列,那么出栈序列T和出队序列S顺序刚好是相反的。

那么,假如我们有两个栈的话,一段序列list通过第一个栈后,再压入第二个栈,这时第二个栈的出栈序列应该和list直接压入队列后的出队序列是一样的。

既然如此,我们用两个栈就可以模拟队列,一个栈专门用来存入数据,记为StackWrite;一个栈专门用来读取数据,记为StackRead。基于上面的结论,我们每次入队时,就把数据压入StackWrite,每次读数据时,就把StackWrite中的数据再压入StackRead,这时StackRead中的栈顶元素就是我们所期望的队首元素

在出队的时候,要注意一点:

  • 如果StackRead中有数据,那么就直接弹出StackRead的栈顶元素;

  • 如果StackRead为空,先考虑把StackWrite中的元素压入StackRead,再弹出StackRead的栈顶元素。

class MyQueue {

Stack stackWrite; // 存数据

Stack stackRead; // 读数据

/** Initialize your data structure here. */

public MyQueue() {

stackWrite = new Stack<>();

stackRead = new Stack<>();

}

/** Push element x to the back of queue. */

public void push(int x) {

stackWrite.push(x);

}

/** Removes the element from in front of queue and returns that element. */

public int pop() {

peek();

return stackRead.pop();

}

/** Get the front element. */

public int peek() {

if (!stackRead.isEmpty()) {

return stackRead.peek();

}

while (!stackWrite.isEmpty()) {

stackRead.push(stackWrite.pop());

}

return stackRead.peek();

}

/** Returns whether the queue is empty. */

public boolean empty() {

return stackRead.isEmpty() && stackWrite.isEmpty();

}

}

/**

  • Your MyQueue object will be instantiated and called as such:

  • MyQueue obj = new MyQueue();

  • obj.push(x);

  • int param_2 = obj.pop();

  • int param_3 = obj.peek();

  • boolean param_4 = obj.empty();

*/

Q3.5 栈排序

栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作:push、pop、peek 和 isEmpty。当栈为空时,peek 返回 -1。

示例1:

输入:

[“SortedStack”, “push”, “push”, “peek”, “pop”, “peek”]

[[], [1], [2], [], [], []]

输出:

[null,null,null,1,null,2]

示例2:

输入:

[“SortedStack”, “pop”, “pop”, “push”, “pop”, “isEmpty”]

[[], [], [], [1], [], []]

输出:

[null,null,null,null,null,true]

class SortedStack {

Stack p=new Stack<>();

Stack q=new Stack<>();

public SortedStack() {

}

public void push(int val) {

if(p.empty()) p.push(val);

else{

while(!p.empty()&&p.lastElement()<=val){

q.push(p.lastElement());

p.pop();

}

p.push(val);

while(!q.empty()){

p.push(q.lastElement());

q.pop();

}

}

}

public void pop() {

if(!p.empty()) p.pop();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值