1 有效括号
优先刷一遍,先用 java 来刷吧
使用 java 和栈进行模拟 思路, 首先使用 Stack 建立一个栈,使用 push 和 pop 进行操作 判断是否是奇数个,如果是返回错误 转换成字符串数组 对应字符进行遍历,如果左括号将其 push 进入栈中 否则判断是否为空 如果为空且非左括号返回 False
使用栈弹出一个字符,与判断当前字符和弹出字符是否互为左右括号 如果是继续,不是返回 false 最后通过 Stack 是否为空来进行说明
class Solution {
public boolean isValid(String s) {
Stack<Character> stack=new Stack<>();
if(s.length()%2!=0){
return false;
}
char[]s_array=s.toCharArray();
for(int i=0;i<s_array.length;i++){
char tmp=s_array[i];
if(tmp=='{'||tmp=='('||tmp=='['){
stack.push(tmp);
}else{
//如果只有2个字符并且先出现右边字符,栈是空的
if(stack.empty())
return false;
char s_top=stack.pop();
if(tmp==')'&&s_top!='('){
return false;
}
if(tmp=='}'&&s_top!='{'){
return false;
}
if(tmp==']'&& s_top!='['){
return false;
}
}
}
return stack.empty();
}
}
2 构建一个最小栈
思路:使用一个辅助栈来进行辅助,辅助栈只保存比当前栈顶元素小的元素进栈,
class MinStack {
private Stack<Integer> stack;
private Stack<Integer>MinStack;
public MinStack() {
stack=new Stack<>();
MinStack=new Stack<>();//min stack存储降序元素,如果出现的值比minstack最小的小就push,
}
public void push(int val) {
stack.push(val);
if(MinStack.isEmpty()||val<=MinStack.peek()){
MinStack.push(val);
}
}
public void pop() {
if(stack.pop().equals(MinStack.peek())){
MinStack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return MinStack.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
3 用栈实现队列
这题也是经典的题目,面试手撕的常客
分析一波: 栈是先进后出,队列是先进先出
void push(int x)将元素 x 推到队列的末尾int pop()从队列的开头移除并返回元素int peek()返回队列开头的元素boolean empty()如果队列为空,返回true;否则,返回false栈 A 和栈 B Push: 将数据推入栈 A Peek:分类讨论:A 有数据,将 A 的数据依次 pop,然后 push 进入栈 B,最后栈 B 弹出。 B 有数据进行 peek A 无数据返回-1,因为为空栈 Pop:调用 peek,然后弹出栈 B 的开头元素,返回 peek 的值
class MyQueue {
private Stack<Integer> A;
private Stack<Integer>B;
public MyQueue() {
A=new Stack<>();
B=new Stack<>();
}
public void push(int x) {
A.push(x);
//用栈实现队列
}
public int pop() {
//将队首元素返回并且移除
int peek=peek();
B.pop();//栈b是进行将元素替换内容
return peek;
}
public int peek() {//peek这个返回队首元素
//栈B不为空
if(!B.isEmpty()){
return B.peek();
}
if( A.isEmpty()){
return -1;//栈A为空的话说明没有数据
}
while(!A.isEmpty()){
B.push(A.pop());
}
return B.peek();
}
public boolean empty() {
return A.isEmpty()&&B.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
4 LeetCode 394 字符串解码
这道题目通过辅助栈来进行运算
class Solution {
public String decodeString(String s) {
//通过解析[]来进行计算,当出现]将栈内元素全部弹出
StringBuilder res=new StringBuilder();
int multi=0;
LinkedList<Integer> stackmulti=new LinkedList<>();//存储出现的数字次数
LinkedList<String> stackres=new LinkedList<>();//存储出现的元素次数[前
for(Character c:s.toCharArray()){
if(c=='['){
stackmulti.addLast(multi);//因为[前面一般是数字,multi已经处理好了
stackres.addLast(res.toString());//接下来的数字后面可能是字母也已经处理好了
multi=0;//重新将数字归0
res=new StringBuilder();//重新建立空字符串
}
else if(c==']'){//遇到]将之前的数字和字母进行运算
StringBuilder tmp=new StringBuilder();//创建一个
int cur_multi=stackmulti.removeLast();
for(int i=0;i<cur_multi;i++){
tmp.append(res);
}
res=new StringBuilder(stackres.removeLast()+tmp);//这一步将之前的保存在栈顶的元素和他们进行合并
}
else if(c>='0'&& c<='9')
multi=multi*10+Integer.parseInt(c.toString());//这里是为了多位数字进行处理的方法
else res.append(c);
}
return res.toString();
}
}
思路,使用两个栈,对于字符串和数字进行分别存储,存储其数字和字符的内容 首先建立两个栈,一个字符串一个数字 定义初始的数字为 0
遍历字符: 如果字符是 0 到 9 之间,mulit=10*mult+Integer.pasetINt(c.toString () 如果普通字符 res 进行添加 如果是【进行处理,数字已经处理好了直接添加,因为也可能有字符串在数字前面 abc 3 这种,所以也进行添加
如果是】 弹出 multi 的数据,进行构建一个 Stringbuilder,multi 是几就对 数据 append 几次,最后返回的是字符串的栈顶元素来和组成的这个元素进行组装。
5 数据流的中位数
这道题的关键是两个堆的维护 堆 A 存储较大的元素的部分是小顶堆(默认就是小顶堆),元素个数比堆 B 要多 堆 B 存储较小的元素,是大顶堆,元素个数小于等于堆 A
class MedianFinder {
Queue<Integer>A,B;
public MedianFinder() {
A=new PriorityQueue<>();// 小顶堆
B=new PriorityQueue<>((x,y)->(y-x));
}
public void addNum(int num) {
if(A.size()!=B.size()){
A.add(num);//A保存较大的元素小顶堆,A的个数也比较多
B.add(A.poll());
}else{
B.add(num);
A.add(B.poll());//小元素的大顶堆这一步是为了包装A的数目小于B的数目使得数据满足上面的部分
}
}
public double findMedian() {
if (A.size()!=B.size()){
return A.peek();//A是小顶堆存储较大的部分的数据
}else{
return (A.peek()+B.peek())/2.0;
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/