20. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

示例 1:

输入: "()"

输出: true

示例 2:

输入: "()[]{}"

输出: true

示例 3:

输入: "(]"

输出: false

示例 4:

输入: "([)]"

输出: false

示例 5:

输入: "{[]}"

输出: true

solution1 往stack放右括号

class Solution {
public boolean isValid(String s) {
//整一个栈
Stack<Character> stack = new Stack<Character>();
for (char c : s.toCharArray()) {
if (c == '{') stack.push('}');
else if (c == '[') stack.push(']');
else if (c == '(') stack.push(')');
else if (stack.isEmpty() || stack.pop() != c) return false;
}
return stack.isEmpty();
}
}

solution2 往stack放左括号

class Solution {
public boolean isValid(String s) {
if (s.length() == 0) return true;
if ((s.length() & 1) == 1) return false;
Stack<Character> stack = new Stack<>();
Map<Character,Character> map = new HashMap<>();
map.put(')','(');
map.put(']','[');
map.put('}','{');
for (int i = 0 ;i < s.length();i++) {
char c = s.charAt(i);
if (c == '(' || c == '[' || c == '{'){
stack.push(c);
}else{
if (stack.size() == 0 || map.get(c) != stack.pop()) {
return false;
}
}
}
return stack.isEmpty(); }
}

solution3 暴力解法,遍历数组,有对称消掉并继续,没对称结束

class Solution {
// private static final Map<Character,Character> = new HashMap<>()
public boolean isValid(String s) {
if (s.length() == 0) return true; //空
if ((s.length() & 1) == 1) return false; // 奇数、位运算
int length;
do{
length = s.length();
s = s.replace("()","").replace("[]","").replace("{}","");
}while(length!=s.length());
return s.length() == 0;
}
}

solution4 字符串加递归

class Solution {
public boolean isValid(String s) {
if (s.contains("()") || s.contains("[]") || s.contains("{}")) {
return isValid(s.replace("()","").replace("[]","").replace("{}",""));
}else {
return "".equals(s);
}
}
}

155. 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。

pop() —— 删除栈顶的元素。

top() —— 获取栈顶元素。

getMin() —— 检索栈中的最小元素。

示例:

输入:

["MinStack","push","push","push","getMin","pop","top","getMin"]

[[],[-2],[0],[-3],[],[],[],[]]

输出:

[null,null,null,null,-3,null,0,-2]

解释:

MinStack minStack = new MinStack();

minStack.push(-2);

minStack.push(0);

minStack.push(-3);

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

minStack.pop();

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

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

提示:

pop、top 和 getMin 操作总是在 非空栈 上调用。

solution1

//整两个栈
class MinStack {
Stack<Integer> stack;
Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
} public void push(int x) {
stack.push(x);
if (minStack.isEmpty() || x <= minStack.peek()) minStack.push(x);
} public void pop() {
if (stack.pop().equals(minStack.peek())) minStack.pop();
} public int top() {
return stack.peek();
} public int getMin() {
return minStack.peek();
}
}

solution2

//一个栈
class MinStack {
Stack<Integer> stack;
Integer i;
public MinStack() {
stack = new Stack<>();
} public void push(int x) {
if (i != null && x <= i) {
stack.push(i);
i = x;
}
if (i == null) i = x;
stack.push(x);
} public void pop() {
if (stack.pop().equals(i) && !stack.isEmpty()) {
i = stack.pop();
}
if (stack.isEmpty()) i = null;
} public int top() {
return stack.peek();
} public int getMin() {
return i;
}
}
class MinStack {
int min = Integer.MAX_VALUE;
Stack<Integer> stack = new Stack<Integer>();
public void push(int x) {
//当前值更小
if(x <= min){
//将之前的最小值保存
stack.push(min);
//更新最小值
min=x;
}
stack.push(x);
} public void pop() {
//如果弹出的值是最小值,那么将下一个元素更新为最小值
if(stack.pop() == min) {
min=stack.pop();
}
} public int top() {
return stack.peek();
} public int getMin() {
return min;
}
}

solution3

//存差值
class MinStack {
Stack<Long> stack;
long i;
/** initialize your data structure here. */
public MinStack() {
stack = new Stack<>();
} public void push(int x) {
if (stack.isEmpty()){
i = x;
stack.push(x-i);
}else {
if (x < i) {
stack.push(x-i);
i = x;
}else{
stack.push(x-i);
} }
} public void pop() {
Long pop = stack.pop();
//弹出后恢复上一个最小值
if ( pop < 0 ) {
i = i - pop;
} } public int top() {
long top = stack.peek();
if (top < 0) {
return (int)i;
}else{
return (int)(top + i);
}
} public int getMin() {
return (int)i;
}
}

84. 柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。



以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。



图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:

输入: [2,1,5,6,2,3]

输出: 10

solution1

//暴力解法1
//时间复杂度为(n^3)Java 超时
class Solution {
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) return 0;
int max = heights[0];
for (int i = 0; i < heights.length; i ++) {
for (int j = i; j < heights.length; j ++) {
//每两个之间的最小值为高
int min = heights[j];
for (int k = i;k <= j; k++){
min = Math.min(min,heights[k]);
max = Math.max(max,min*(k-i+1));
}
}
}
return max;
}
}

solution2

//暴力2,以每个柱子为最低点,找到对应的矩形
//时间复杂度为(n^2)
class Solution {
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) return 0;
int max = 0;
for (int i = 0; i < heights.length; i ++) {
//遍历左边,找是否有比本身大的
int left = i;
while (left > 0 && heights[left-1] >= heights[i]){
left --;
}
//遍历右边,找是否有比本身小的
int right = i;
while (right < heights.length - 1 && heights[right+1] >= heights[i]) {
right ++;
}
max = Math.max((right - left + 1)*heights[i],max);
}
return max;
}
}

solution3

// 时间、空间复杂度均为O(n)
// 每个的左右边界为比它小的值,栈从小到大放,可以保证左边界,遇到比它小的为右边界,即可计算矩形面积
class Solution {
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) return 0;
Stack<Integer> stack = new Stack<>();
stack.push(-1);
int max = 0;
//按从小到大插入栈,确保每个插入的值知道它的左边界,遇到比它小的即确定右边界
for (int i = 0; i < heights.length; i ++) {
while (stack.peek() != -1 && heights[stack.peek()] >= heights[i]) {
max = Math.max(max,heights[stack.pop()] * (i - stack.peek() - 1));
// 确定了左右边界,右边界为比它小的,左边界为栈里比它小的后一位
}
stack.push(i);
}
//清空栈
while (stack.peek() != -1)
max = Math.max(max, heights[stack.pop()] * (heights.length - stack.peek() - 1));
return max;
}
}

solution4

//用两个数组
class Solution {
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) {
return 0;
}
//整两个数组记录每个数的左右边界,即从左算和右算的最小值
int[] lessFromLeft = new int[heights.length];
int[] lessFromRight = new int[heights.length];
lessFromRight[heights.length - 1] = heights.length;
lessFromLeft [0] = -1;
// 确定左边界
for (int i = 1;i < heights.length; i++){
int p = i-1;
while (p >= 0 && heights[p] >= heights[i]) {
p = lessFromLeft[p];
}
lessFromLeft[i] = p;
}
//确定右边界
for (int i = heights.length - 2;i >= 0;i --){
int p = i + 1;
while(p < heights.length && heights[p] >= heights[i]){
p = lessFromRight[p];
}
lessFromRight[i] = p;
}
int max = 0;
for (int i = 0; i < heights.length; i ++){
max = Math.max(max,(lessFromRight[i]-lessFromLeft[i]-1)*heights[i]);
}
return max; }
}

239. 滑动窗口最大值

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

进阶:

你能在线性时间复杂度内解决此题吗?

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3

输出: [3,3,5,5,6,7]

解释:

滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3

1 [3 -1 -3] 5 3 6 7 3

1 3 [-1 -3 5] 3 6 7 5

1 3 -1 [-3 5 3] 6 7 5

1 3 -1 -3 [5 3 6] 7 6

1 3 -1 -3 5 [3 6 7] 7

提示:

1 <= nums.length <= 10^5

-10^4 <= nums[i] <= 10^4

1 <= k <= nums.length

solution1 暴力法

//时间复杂度为O(nk),Java代码无法通过
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length-k+1];
for (int i = 0;i < nums.length-k+1;i ++) {
int max = Integer.MIN_VALUE;
for (int j = i;j < i+k;j++) {
max = Math.max(max,nums[j]);
}
result[i] = max;
}
return result; }
}

solution2 双端队列

class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 0 || k == 0) return nums; //判空 int[] result = new int[nums.length-k+1]; //返回的结果 Deque<Integer> dq = new ArrayDeque<>(); // 双端队列,从小到大
for (int i = 0; i < nums.length ;i ++){
if (!dq.isEmpty() && dq.peek() < i - k + 1) {
dq.poll();
}
//移除队列内比要插入的小的元素,保证最后一位为最大值
while (!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]) {
dq.pollLast();
}
dq.offer(i);
if (i-k+1 >= 0){ //遍历到第3个开始存值
result[i-k+1] = nums[dq.peek()];
}
}
return result; }
}

solution3 分块法

class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return null;
}
int[] maxfromleft = new int[nums.length];
int[] maxfromright = new int[nums.length]; maxfromleft[0] = nums[0];
maxfromright[nums.length - 1] = nums[nums.length - 1];
//分块 整两个数组记录
for (int i = 1;i < nums.length;i++) {
//从左到右遍历 保证块内从左到右增大
if (i%k == 0) maxfromleft[i] = nums[i];
else maxfromleft[i] = Math.max(maxfromleft[i-1],nums[i]); //从右到左遍历 保证块内从右到左递增
int j = nums.length - 1 - i;
if (j%k == 0) maxfromright[j] = nums[j];
else maxfromright[j] = Math.max(maxfromright[j+1],nums[j]);
}
int[] output = new int[nums.length - k + 1];
for (int i = 0;i < nums.length - k +1;i ++) {
output[i] = Math.max(maxfromleft[i+k-1],maxfromright[i]);
//取窗口涉及到的左块内最右的值,右块内最左的值进行比较
}
return output;
}
}
//用lamda
public static int[] slidingWindowMax(final int[] in, final int w) {
final int[] max_left = new int[in.length];
final int[] max_right = new int[in.length]; max_left[0] = in[0];
max_right[in.length - 1] = in[in.length - 1]; for (int i = 1; i < in.length; i++) {
max_left[i] = (i % w == 0) ? in[i] : Math.max(max_left[i - 1], in[i]); final int j = in.length - i - 1;
max_right[j] = (j % w == 0) ? in[j] : Math.max(max_right[j + 1], in[j]);
} final int[] sliding_max = new int[in.length - w + 1];
for (int i = 0, j = 0; i + w <= in.length; i++) {
sliding_max[j++] = Math.max(max_right[i], max_left[i + w - 1]);
}

LeetCode 栈与队列篇(12、155、84、239)的更多相关文章

  1. leetcode 栈和队列类型题

    1,Valid Parentheses bool isVaild1(string& s) { // 直接列举,不易扩展 stack<char> stk; ; i < s.le ...

  2. LeetCode刷题 --杂篇 --数组,链表,栈,队列

    武汉加油,中国加油.希望疫情早日结束. 由于疫情,二狗寒假在家不能到处乱逛,索性就在家里系统的刷一下算法的内容,一段时间下来倒也有些小小的收获.只是一来家中的小破笔记本写起博客来实在不是很顺手,二来家 ...

  3. Python笔记_第二篇_面向过程_第二部分_2.路径、栈和队列、内存修改

    这一部分分三个主题进行讲解,主要为后面的模块.包.第三方库的概念补充一些相关的内容. 1. 路径(Path): 相对路径和绝对路径. 举例1:我们先导入一个os库(模块)来观察一下路径 import ...

  4. LeetCode入门指南 之 栈和队列

    栈 155. 最小栈 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- 删除栈顶的元素. top( ...

  5. 栈和队列数据结构的相互实现[LeetCode]

    栈是先进后出,队列是先进后出,这里讨论一下两种数据结构之间的相互实现. 一.用两个栈实现队列 我们用一个栈来实现队列的进队操作(栈A),用另一个栈来实现队列的出队操作(栈B). 1.入队列: 把元素放 ...

  6. 【LeetCode题解】232_用栈实现队列(Implement-Queue-using-Stacks)

    目录 描述 解法一:在一个栈中维持所有元素的出队顺序 思路 入队(push) 出队(pop) 查看队首(peek) 是否为空(empty) Java 实现 Python 实现 解法二:一个栈入,一个栈 ...

  7. LeetCode 232. 用栈实现队列(Implement Queue using Stacks) 4

    232. 用栈实现队列 232. Implement Queue using Stacks 题目描述 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从 ...

  8. leetcode刷题记录——栈和队列

    题目 232.用栈实现队列 class MyQueue { private Stack<Integer> in = new Stack<>(); private Stack&l ...

  9. ACM金牌选手讲解LeetCode算法《栈和队列的高级应用》

    大家好,我是编程熊,双非逆袭选手,字节跳动.旷视科技前员工,ACM金牌,保研985,<ACM金牌选手讲解LeetCode算法系列>作者. 上一篇文章讲解了<线性表>中的数组.链 ...

  10. LeetCode通关:栈和队列六连,匹配问题有绝招

    刷题路线参考: https://github.com/chefyuan/algorithm-base https://github.com/youngyangyang04/leetcode-maste ...

随机推荐

  1. The method dismissDialog(int) from the type Activity is deprecated

    The method showDialog(int) from the type Activity is deprecated in android?   up vote6down votefavor ...

  2. mooc第四单元《管理团队》单元测试

    第四单元<管理团队>单元测试 返回 本次得分为:6.00/10.00, 本次测试的提交时间为:2020-08-30, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 判断(2分 ...

  3. 低代码助力微信小程序对接,提升开发效率

    摘要:本文由葡萄城技术团队原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 微信小程序相信大家都用过,相较于APP,微信小程序的优势在于其便 ...

  4. 这款 7k Star 的国产监控系统,真不错!

    我们都知道天下没有"永不宕机"的系统,但每次线上出问题都要拉出一个程序员"祭天".所以一款靠谱.好用的监控工具就显得十分重要,它可以在生产环境出故障的第一时间发 ...

  5. 自然数的拆分问题(lgP2404)

    dfs.又调了一个小时,窝果然菜 需要传递的变量分别为目前搜索的数字:目前所有选中数字的和:目前所选数字个数. 见注释. #include<bits/stdc++.h> using nam ...

  6. 带您了解 O2OA 流程中的人工活动处理方式

    这次咱们来介绍 O2OA (翱途) 开发平台流程引擎中的人工活动的处理方式和逻辑,O2OA (翱途) 主要采用拖拽可视化开发的方式完成流程的设计和配置,不需要过多的代码编写,业务人员可以直接进行修改操 ...

  7. 开源模型 Zephyr-7B 发布——跨越三大洲的合作

    最近我们刚刚发布了新的开源模型 Zephry-7B,这个模型的诞生离不开全球三大洲开源社区的协作 ️. 我们的 CSO Thomas 录了一个视频介绍了它的起源故事: 就在几个月前,巴黎的一个新团队发 ...

  8. python列表删除元素之del,pop()和remove()

    del函数 如果知道要删除元素在列表中的位置,可以使用del语句: list_1 = ['one', 'two', 'three'] print(list_1) del list_1[0] print ...

  9. 三菱PLC 轻松数采

    目前市面上数采的软件有很多,但是用的最为省力最为简单的就是kepserver了,在kepserver的应用中,有对应的三菱驱动针对于三菱PLC,三菱驱动支持多个Mitsubishi 协议,包括 MEL ...

  10. 【GIT】学习day03 | 如何生成并配置SSH公钥【外包杯】

    快速笔记: 1.注册并激活码云账号 2.生成并配置SSH公钥(运行ssh -t git@gitee.com 检测SSH公钥是否配置成功) 3.创建空白的码云仓库 4.把本地项目上传到码云对应的空白仓库 ...