LC20
package com.wang.leetcode.Stack;
import java.util.Stack;
//有效的括号
//输入字符串
//输出布尔值,判断字符串是否有效
//利用栈先进后出的特性
class Solution20{
public boolean isValid(String s){
Stack<Character>left=new Stack<>();
for (char c:s.toCharArray()){
if (c=='('||c=='['||c=='{'){
left.push(c);
}
else {
if (!left.isEmpty()&&leftOf(c)==left.peek()){
left.pop();
}else return false;
}
}
return left.isEmpty();
}
char leftOf(char c){
if (c==')')return '(';
if (c=='}')return '{';
return '[';
}
}
public class LC20 {
public static void main(String[] args) {
Solution20 solution20=new Solution20();
String s = "(]";
System.out.println(solution20.isValid(s));
}
}
LC232
package com.wang.leetcode.StackAndQueue;
import java.util.Stack;
//用栈实现队列
//仅使用两个栈实现先入先出队列
/*
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
*/
class MyQueue{
private Stack<Integer>s1,s2;
//s1:用于接收新元素(push操作)
//s2:用于取出元素(pop/peek操作)
public MyQueue(){
s1=new Stack<>();
s2=new Stack<>();
}
// 添加元素到队尾
public void push(int x){
s1.push(x);
}
//删除队头元素并返回
public int pop(){
peek();//确保 s2 里有元素,如果 s2 为空,peek() 会把 s1 的所有元素倒入 s2,保证 s2 的栈顶就是队列的队头。
return s2.pop();//移除并返回栈s2的顶部元素
}
//返回队列开头的元素
public int peek(){
if (s2.isEmpty())
while (!s1.isEmpty())s2.push(s1.pop());
return s2.peek();//查看s2的栈顶但不移除
}
public boolean empty(){
return s1.isEmpty()&&s2.isEmpty();
}
}
public class LC232 {
}
LC155
package com.wang.leetcode.StackAndQueue;
import java.util.Stack;
//最小栈
//设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
//实现 MinStack 类:
//MinStack() 初始化堆栈对象。
//void push(int val) 将元素val推入堆栈。
//void pop() 删除堆栈顶部的元素。
//int top() 获取堆栈顶部的元素。
//int getMin() 获取堆栈中的最小元素。
//每个元素入栈时,还要记下来当前栈中的最小值。比方说,可以用一个额外的栈 minStk 来记录栈中每个元素入栈时的栈中的最小元素是多少,这样每次删除元素时就能快速得到剩余栈中的最小元素了。
class MinStack1{
// 记录栈中的所有元素
Stack<Integer> stk = new Stack<>();
// 阶段性记录栈中的最小元素
Stack<Integer> minStk = new Stack<>();
public void push(int val){
stk.push(val);
// 维护 minStk 栈顶为全栈最小元素
if (minStk.isEmpty()||val<=minStk.peek()){
minStk.push(val);
}else minStk.push(minStk.peek());
}
public void pop(){
stk.pop();
minStk.pop();
}
public int top(){
return stk.peek();
}
public int getMin(){
return minStk.peek();
}
}
public class LC155 {
}
LC239
package com.wang.leetcode.StackAndQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
//滑动窗口最大值
//给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
//返回 滑动窗口中的最大值 (数组的形式)
//使用一个队列充当不断滑动的窗口
class Solution239{
// 单调队列的实现
class MonotonicQueue{
LinkedList<Integer> q = new LinkedList<>();
public void push(int n){
// 将小于 n 的元素全部删除
while (!q.isEmpty()&&q.getLast()<n){//保持队列单调递减
q.pollLast();//移除掉尾部的元素(即比n小的元素,因为题目要的是最大的,所以这些元素不可能再用到了)
}
q.addLast(n);//删完比n小的元素之后把n加入尾部
}
public int max(){
return q.getFirst();//获取头部元素的值,不移除
}
public void pop(int n){//移除队头元素(如果等于 n)
//当某个元素(通常是滑动窗口左边界)离开窗口时,检查它是否是当前队列的最大值(即队头元素)。
//如果是,则移除它(因为它已经不在窗口内)。
if (n==q.getFirst()){//只需要担心最大值
q.pollFirst();//移除头部元素
}
}
}
public int[] maxSlidingWindow(int[] nums, int k){
List<Integer>res=new ArrayList<>();
MonotonicQueue window = new MonotonicQueue();
for (int i = 0; i < nums.length; i++) {
if (i<k-1){ // 先填满窗口的前 k - 1
window.push(nums[i]);
}else {
window.push(nums[i]);
res.add(window.max());
window.pop(nums[i-k+1]);//从i=2的情况考虑
}
}
int[]arr=new int[res.size()];
for (int i = 0; i < res.size(); i++) {
arr[i]= res.get(i);
}
return arr;
}
}
public class LC239 {
public static void main(String[] args) {
Solution239 solution239=new Solution239();
int[]nums={1,3,-1,-3,5,3,6,7};
int k=3;
System.out.println(Arrays.toString(solution239.maxSlidingWindow(nums,k)));
}
}
LC394
package com.wang.leetcode.StackAndQueue;
import java.util.ArrayDeque;
import java.util.Deque;
//字符串解码
//给定一个经过编码的字符串,返回它解码后的字符串
class Solution394{
public String decodeString(String s) {
Deque<Integer> countStack = new ArrayDeque<>(); // 存储数字
Deque<String> stringStack = new ArrayDeque<>(); // 存储字符串
String currentString = ""; // 当前解码字符串
int k = 0; // 当前的倍数
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
k = k * 10 + (c - '0');
} else if (c == '[') {
// 遇到 '[',将当前的字符串和数字推入各自的栈
countStack.push(k);
stringStack.push(currentString);
currentString = ""; // 重置当前字符串
k = 0; // 重置倍数
} else if (c == ']') {
// 遇到 ']',解码
StringBuilder temp = new StringBuilder(stringStack.pop());
int repeatTimes = countStack.pop();
for (int i = 0; i < repeatTimes; i++) {
temp.append(currentString); // 重复当前字符串
}
currentString = temp.toString(); // 更新当前字符串
} else {
// 如果是字母,直接加到当前字符串
currentString += c;
}
}
return currentString;
}
}
public class LC394 {
public static void main(String[] args) {
Solution394 solution394= new Solution394();
String s = "3[a2[c]]";
System.out.println(solution394.decodeString(s));
}
}
这个好难。。。