【Leetcode】第十四日--栈

一、题目列表

1441. 用栈操作构建数组
1021. 删除最外层的括号
1700. 无法吃午餐的学生数量
1381. 设计一个支持增量操作的栈

二、解题思路

1.用栈操作构建数组

题目描述:

给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3…, n} 中依序读取一个数字。

请使用下述操作来构建目标数组 target :

Push:从 list 中读取一个新元素, 并将其推入数组中。
Pop:删除数组中的最后一个元素。
如果目标数组构建完成,就停止读取更多元素。
题目数据保证目标数组严格递增,并且只包含 1 到 n 之间的数字。

请返回构建目标数组所用的操作序列。

题目数据保证答案是唯一的。

//先用栈直观的体会这道题
class Solution {
    public List<String> buildArray(int[] target, int n) {
        List<String> ret = new ArrayList<>();//返回结果
        Stack<Integer> stack = new Stack<>();//将数组元素入栈

        for(int num = 1,index = 0; num <= n && index < target.length ; num++){
            //先将数和操作存放
            stack.add(num);
            ret.add("Push");
            //如果数组中不存在stack中的元素,则弹出
            if(target[index] != stack.peek()){
                stack.pop();
                ret.add("Pop");
            }else{
                index++; //符合要求则游标右移
            }
        }
        return ret;
    }
}
//n的值是1-n,数组从下标开始。
//只要n在数组中找得到,则进行push,找不到则先push再pop。
class Solution {
    public List<String> buildArray(int[] target, int n) {
        List<String> ret = new ArrayList<>();//返回结果
        for(int num = 1,index = 0; num <= n && index < target.length ; num++){
            if(num == target[index]){
                ret.add("Push");
                index++;
            }else{
                ret.add("Push");
                ret.add("Pop");
            }
        }
        return ret;
    }
}

2.删除最外层的括号

题目描述:

有效括号字符串为空 “”、“(” + A + “)” 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。

例如,“”,“()”,“(())()” 和 “(()(()))” 都是有效的括号字符串。
如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。

给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。

对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。

class Solution {
    public String removeOuterParentheses(String s) {
        int pre = 0;
        int count = 0;
        String ret = "";
        for(int i = 0; i < s.length(); i++){
            //计数,遇到(加一,)减一
            if(s.charAt(i) == '('){
                count++;
            }else{
                count--;
            }
            
            //当计数为0时,说明左边是原语,去掉最外层括号
            if(count == 0){
                for(int j = pre+1; j <= i-1; j++){
                    ret += s.charAt(j);
                }
                pre = i +1;
            }
        }

        return ret;
    }
}

3.无法吃午餐的学生数量

题目描述:

学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:

如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。

给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。

//用队列存储学生人数
class Solution {
    public int countStudents(int[] students, int[] sandwiches) {
        Queue<Integer> stu = new LinkedList<>();
        for(int student : students){
            stu.offer(student);//将数组转为队列
        }

        for(int i = 0; i < sandwiches.length; i++){
            //队列为空时说明学生都满足了
            if(stu.isEmpty()){
                return 0;
            }
            //记录学生队列长度
            int size = stu.size();
            boolean isLike = false;
            for(int s = 0; s < size; s++){
                int poll = stu.poll();
                if(poll != sandwiches[i]){
                    stu.offer(poll);//将学生移动至队列尾部
                }else{
                    //顶层的三明治被人挑选,继续下一块的判断
                    isLike = true;
                    break;
                }
            }

            if(!isLike){
                //最顶层的三明治没人挑选时
                return size;
            }
        }

        return stu.size();
    }
}
//统计students喜爱各个口味的人数,和三明治的对应
class Solution {
    public int countStudents(int[] students, int[] sandwiches) {
        int[] counts = new int[2];
        for(int num : students){
            ++counts[num];
        }

        int len = sandwiches.length;
        for(int i = 0; i < len; i++){
            if(counts[sandwiches[i]] > 0){
                --counts[sandwiches[i]];
            }else{
                return len - i;
            }
        }

        return 0;
    }
}

4.设计一个支持增量操作的栈

题目描述:

请你设计一个支持下述操作的栈。

实现自定义栈类 CustomStack :

CustomStack(int maxSize):用 maxSize 初始化对象,maxSize 是栈中最多能容纳的元素数量,栈在增长到 maxSize 之后则不支持 push 操作。
void push(int x):如果栈还未增长到 maxSize ,就将 x 添加到栈顶。
int pop():弹出栈顶元素,并返回栈顶的值,或栈为空时返回 -1 。
void inc(int k, int val):栈底的 k 个元素的值都增加 val 。如果栈中元素总数小于 k ,则栈中的所有元素都增加 val 。

//用数组进行模拟
class CustomStack {

    int[] stack;
    int top; //记录栈顶位置
    public CustomStack(int maxSize) {
        stack = new int[maxSize];
        top = -1;
    }
    
    public void push(int x) {
        if(top != stack.length - 1){
            ++top;
            stack[top] = x;
        }
    }
    
    public int pop() {
        if(top == -1){
            return -1;
        }

        --top;
        return stack[top+1];
    }
    
    public void increment(int k, int val) {
        int min = Math.min(k, top +1);

        for(int i = 0; i < min; i++){
            stack[i] += val;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值