栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
刷题坚持每一天,以下题目引用自:力扣(LeetCode)
原题链接:1441. 用栈操作构建数组
给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3…, n} 中依序读取一个数字。
请使用下述操作来构建目标数组 target :
- Push:从 list 中读取一个新元素, 并将其推入数组中。
- Pop:删除数组中的最后一个元素。
如果目标数组构建完成,就停止读取更多元素。
题目数据保证目标数组严格递增,并且只包含 1 到 n 之间的数字。
请返回构建目标数组所用的操作序列。
题目数据保证答案是唯一的。
示例 1:
输入:target = [1,3], n = 3
输出:[“Push”,“Push”,“Pop”,“Push”]
解释:
读取 1 并自动推入数组 -> [1]
读取 2 并自动推入数组,然后删除它 -> [1]
读取 3 并自动推入数组 -> [1,3]
思路:
用
ret
计数,每一个值都进栈,然后判断和数组内值是否相等,相等则数组内的值向后走一位,不相等则出栈。
char ** buildArray(int* target, int targetSize, int n, int* returnSize){
char** ans = (char**)malloc(sizeof(char*)*n*2);
int ret = 1;
int count = 0;
int i = 0;
while(i < targetSize && ret <= n){
ans[count] = (char*)malloc(sizeof(char)*5);
ans[count++] = "Push";
if(target[i] == ret) ++i;
else if(target[i] != ret){
ans[count] = (char*)malloc(sizeof(char)*4);
ans[count++] = "Pop";
}
++ret;
}
*returnSize = count;
return ans;
}
原题链接:1021. 删除最外层的括号
有效括号字符串为空 “”、“(” + A + “)” 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。
例如,“”,“()”,“(())()” 和 “(()(()))” 都是有效的括号字符串。
如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。
给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。
对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。
示例 1:
输入:s = “(()())(())”
输出:“()()()”
解释:
输入字符串为 “(()())(())”,原语化分解得到 “(()())” + “(())”,
删除每个部分中的最外层括号后得到 “()()” + “()” = “()()()”。
思路:
用
stack
的值为零判断为最外侧括号,进行忽略不写入。
char * removeOuterParentheses(char * s){
int stack = 0;
int ret = 0;
int i;
for(i = 0; s[i] != '\0'; ++i){
if(s[i] == '('){
if(stack != 0) s[ret++] = s[i];
++stack;
}
else{
--stack;
if(stack != 0) s[ret++] = s[i];
}
}
s[ret] = '\0';
return s;
}
原题链接:1700. 无法吃午餐的学生数量
学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
- 如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
- 否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。
示例 1:
输入:students = [1,1,0,0], sandwiches = [0,1,0,1]
输出:0
解释:
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,0,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,0,1,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [0,1,1],三明治栈为 sandwiches = [1,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,1,0]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1,0],三明治栈为 sandwiches = [0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1],三明治栈为 sandwiches = [1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [],三明治栈为 sandwiches = []。
所以所有学生都有三明治吃。
思路:
先统计喜欢方形和圆形的各总人数,然后在根据栈顶三明治形状,判断有多少人吃不到三明治。
int countStudents(int* students, int studentsSize, int* sandwiches, int sandwichesSize){
int ans[2] = {0};
int i;
for(i = 0; i < studentsSize; ++i)
++ans[students[i]];
for(i = 0; i < sandwichesSize; ++i){
if(ans[sandwiches[i]] == 0) break;
--ans[sandwiches[i]];
}
return ans[0] + ans[1];
}
原题链接:1381. 设计一个支持增量操作的栈
请你设计一个支持下述操作的栈。
实现自定义栈类 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 。
示例 1:
输入:
[“CustomStack”,“push”,“push”,“pop”,“push”,“push”,“push”,“increment”,“increment”,“pop”,“pop”,“pop”,“pop”]
[[3],[1],[2],[],[2],[3],[4],[5,100],[2,100],[],[],[],[]]
输出:
[null,null,null,2,null,null,null,null,null,103,202,201,-1]
解释:
CustomStack customStack = new CustomStack(3); // 栈是空的 []
customStack.push(1); // 栈变为 [1]
customStack.push(2); // 栈变为 [1, 2]
customStack.pop(); // 返回 2 --> 返回栈顶值 2,栈变为 [1]
customStack.push(2); // 栈变为 [1, 2]
customStack.push(3); // 栈变为 [1, 2, 3]
customStack.push(4); // 栈仍然是 [1, 2, 3],不能添加其他元素使栈大小变为 4
customStack.increment(5, 100); // 栈变为 [101, 102, 103]
customStack.increment(2, 100); // 栈变为 [201, 202, 103]
customStack.pop(); // 返回 103 --> 返回栈顶值 103,栈变为 [201, 202]
customStack.pop(); // 返回 202 --> 返回栈顶值 202,栈变为 [201]
customStack.pop(); // 返回 201 --> 返回栈顶值 201,栈变为 []
customStack.pop(); // 返回 -1 --> 栈为空,返回 -1
思路:
通过对数组的增加(Push)减少(Pop)元素和对数组元素的处理(Inc)实现栈的操作。
typedef struct {
int sta[1001];
int top;
int size;
} CustomStack;
CustomStack* customStackCreate(int maxSize) {
CustomStack* obj = (CustomStack*)malloc(sizeof(CustomStack));
obj->top = 0;
obj->size = maxSize;
return obj;
}
void customStackPush(CustomStack* obj, int x) {
if(obj->top < obj->size){
obj->sta[obj->top++] = x;
}
}
int customStackPop(CustomStack* obj) {
if(obj->top == 0) return -1;
return obj->sta[--obj->top];
}
void customStackIncrement(CustomStack* obj, int k, int val) {
int min;
int i;
min = obj->top > k ? k : obj->top;
for(i = 0; i < min; ++i){
obj->sta[i] += val;
}
}
void customStackFree(CustomStack* obj) {
free(obj);
}
星球链接:英雄算法联盟
星球里有什么?
【朋友圈】一个极致精准的自律、编程、算法的小圈子。
【算法集训】以月为单位组织算法集训,每天四题,风雨无阻。
【排行榜】每天、每周都会有榜单,激励大家不断进步,不断成长。
【个人规划】每个人都写好自己的规划,也可以查看他人的规划,时刻警醒自己不掉队。
【打卡挑战】每日一题打卡、每日早起打卡、算法集训打卡、规划完成情况打卡。
在星球里做什么?
目前星球人数达到420+,在星球里你能够遇到一群志同道合之人,因为都是花钱进来的,你不会看到任何浑水摸鱼的人,每个人都有自己的每月规划,星主每月都会组织算法集训,每天一起刷题,你可以看到别人的解题报告,取其之长,补己之短。