括号匹配问题:
OJ链接:括号匹配问题
思路:如果是左边括号就一直入栈,当遇到右括号,就将栈顶元素出栈并与该右括号对比是否为一对,如果不是直接return false;当字符串遍历完成,且此时栈为空,则表示结果为true,return true即可。
代码:
public boolean isValid(String s) {
Stack<Character> stack=new Stack<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='(' || s.charAt(i)=='[' || s.charAt(i)=='{')
{
stack.push(s.charAt(i));
}else{
if(stack.empty()) return false;
char tmp=stack.pop();
if(s.charAt(i)==')' && tmp=='(' || s.charAt(i)=='}' && tmp=='{' || s.charAt(i)==']' && tmp=='[' ) continue;
else return false;
}
}
if(stack.empty()) return true;
else return false;
}
栈的弹出压入序列
OJ链接:栈的弹出压入序列
思路:定义两个指针,分别从两个序列开头开始遍历,如果两个指针对应的值不同,则左边一直入栈,直到值相同,则栈顶元素出栈,右边指针后移,若相同再出栈,直到不同为止,重复两个过程,直到右序列遍历完成,若此时栈为空,则表示满足条件
代码:
public boolean IsPopOrder(int[] pushA, int[] popA) {
Stack<Integer> stack = new Stack<>();
int i=0;
int j=0;
for(;i<pushA.length;i++){
stack.push(pushA[i]);
while(!stack.empty() && stack.peek()== popA[j]){
stack.pop();
j++;
}
}
return stack.empty();
}
逆波兰表达式求值
OJ链接:.逆波兰表达式求值
思路:准备一个栈,如果是数字,压栈,遇到符号,出栈两个元素,首先出栈的元素放在符号右边,后面出栈的元素放在符号右边,形成一个表达式,计算表达式结果,将值压栈,遍历完成后 栈里只剩下一个元素,该元素即为所求值。
代码:
public static int evalRPN(String[] tokens) {
Stack<Integer> stack=new Stack<>();
for(int i=0;i<tokens.length;i++){
String s=tokens[i];
if(!s.equals("*") && !s.equals("+") && !s.equals("-") && !s.equals("/") ){
int tmp=Integer.parseInt(s);
stack.push(tmp);
}else{
int nums2=stack.pop();
int nums1=stack.pop();
switch(s){
case "+":
stack.push(nums1+nums2);
break;
case "-":
stack.push(nums1-nums2);
break;
case "*":
stack.push(nums1*nums2);
break;
case "/":
stack.push(nums1/nums2);
break;
}
}
}
return stack.pop();
}
最小栈
OJ链接:最小栈
思路:准备两个栈,一个栈存放压入的元素,另一个栈存放最小的元素,压栈时,只有当第二个栈为空,或压栈的元素小于第二个栈的栈顶元素时,才往第二个栈里放元素,检索最小元素直接看第二个栈栈顶即可,另外,当出栈时出的元素和第二个栈栈顶元素相同,则要同时出栈,
代码:
public Stack<Integer> stack1;
public Stack<Integer> stack2;
public MinStack() {
stack1=new Stack();
stack2=new Stack();
}
public void push(int val) {
stack1.push(val);
if(stack2.empty() || val<=stack2.peek()) stack2.push(val);
}
public void pop() {
if(stack1.pop().equals(stack2.peek())) stack2.pop();
}
public int top() {
return stack1.peek();
}
public int getMin() {
return stack2.peek();
}
用队列实现栈
OJ链接:用队列实现栈
思路:需要两个队列,压栈时,如果第一个队列为空,则直接在在第一个队列入队,如果第一个队列不为空,在第一个队列入队后,第一个队列保留一个元素,其余元素出队,入队到第二个队列。
需要出栈时,如第一个队列不为空,则直接把第一个队列的元素出队,若第一个队列为空,第二个队列保留一个元素,其余元素出队至第一个队列,再把第二个队列仅剩的元素出队,出队完成后,再把第一个队列全部元素入队回第一队,获取栈顶元素的流程类似,只不过第二个队列仅剩的元素无需出队。
代码:
public Queue<Integer> Queue1= new LinkedList<>();
public Queue<Integer> Queue2= new LinkedList<>();
public MyStack() {
}
public void push(int x) {
Queue1.offer(x);
while(Queue1.size()>1){
Queue2.offer(Queue1.poll());
}
}
public int pop() {
if(Queue1.isEmpty()){
while(Queue2.size()>1){
Queue1.offer(Queue2.poll());
}
int tmp=Queue2.poll();
while(Queue1.size()>0){
Queue2.offer(Queue1.poll());
}
return tmp;
}else{
return Queue1.poll();
}
}
public int top() {
if(Queue1.isEmpty()){
while(Queue2.size()>1){
Queue1.offer(Queue2.poll());
}
int tmp=Queue2.poll();
while(Queue1.size()>0){
Queue2.offer(Queue1.poll());
}
Queue2.offer(tmp);
return tmp;
}else{
return Queue1.peek();
}
}
public boolean empty() {
return Queue1.isEmpty() && Queue2.isEmpty();
}
用栈实现队列
OJ链接:用栈实现队列
思路:准备两个对,入队操作时,直接入队即可。出队时,将第一个栈中只保留一个元素,其他元素均出栈再压栈至第二个栈,再将该元素出栈即可,获取队顶元素的操作也类似。
代码:
public Stack<Integer> stack1=new Stack<>();
public Stack<Integer> stack2=new Stack<>();
public MyQueue() {
}
public void push(int x) {
stack1.push(x);
}
public int pop() {
while(stack1.size()>0){
stack2.push(stack1.pop());
}
int tmp=stack2.pop();
while(stack2.size()>0){
stack1.push(stack2.pop());
}
return tmp;
}
public int peek() {
while(stack1.size()>0){
stack2.push(stack1.pop());
}
int tmp=stack2.peek();
while(stack2.size()>0){
stack1.push(stack2.pop());
}
return tmp;
设计循环队列
OJ链接:设计循环队列
思路:用数组实现,定义两个下标指针,一个指向头,一个指向尾,数组需要空出一个空间,不放满,空出空间作为判断队列满的条件。定义一个size,表示当前存放的元素的个数,存放元素时,在尾指针下标的位置存放,然后尾指针+1后再对数组长度取模,取模后才不会越界,删除元素,把头指针位置的元素弹出,头指针+1后取模,判断队列满的条件:因为空出一个位置不存放元素,所以当尾指针+1取模后是头指针,队列已满,当size==0时,队列为空。
代码:
public int[] list;
public int usedsize;
public int front=0;
public int rear=0;
public int length=0;
public MyCircularQueue(int k) {
this.list=new int[k+1];
this.length=k+1;
}
public boolean enQueue(int value) {
if(isFull()) return false;
list[rear]=value;
rear=(rear+1)%length;
usedsize++;
return true;
}
public boolean deQueue() {
if(isEmpty()) return false;
front=(front+1)%length;
usedsize--;
return true;
}
public int Front() {
if(isEmpty()) return -1;
return list[front];
}
public int Rear() {
if(isEmpty()) return -1;
if(rear==0) return list[length-1];
else return list[rear-1];
}
public boolean isEmpty() {
if(usedsize==0) return true;
else return false;
}
public boolean isFull() {
if((rear+1)%length==front) return true;
else return false;
}