一、题目列表
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;
}
}
}