一.栈
栈的内容相对简单,java中用顺序表实现栈,除栈外双向链表也可以实现栈, 栈只有pop,push,peek,empty方法,直接刷题
1. 有效括号序列
public class Solution {
/**
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValid (String s) {
// write code here\
char c;
Stack<Character> eg = new Stack<>();
for (int i = 0; i < s.length(); i ++){
c = s.charAt(i);
if (c == '(' || c == '[' || c == '{'){
eg.push(c);
}else{
if (eg.empty()){
return false;
}else{
char a = eg.peek();
if(a == '(' && c == ')' || a == '[' && c == ']' || a == '{' && c == '}'){
eg.pop();
}else{
return false;
}
}
}
}
return eg.empty();
}
2. 表达式求值
import java.util.*;
public class Solution {
public int solve1 (char ch, int a, int b) {
switch (ch) {
case '+':
return b + a;
case '-':
return b - a;
case '*':
return b * a;
}
return 0;
}
public int solve (String s) {
// write code here
Stack<Character> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
char ch;
int i = 0;
String s1 = "";
short flag1 = 0;
short flag2 = 0;
while (i < s.length()) {
ch = s.charAt(i);
if (!stack1.empty() && stack1.peek() == '*'){
flag1 = 1;
}
if ( ch == ')') {
while (stack1.peek() != '(') {
int eg = solve1(stack1.pop(), stack2.pop(), stack2.pop());
stack2.push(eg);
}
stack1.pop();
if (flag1 == 1 && flag2 >0){
flag2--;
}
i++;
} else {
s1 = "";
while (ch != '+' && ch != '*' && ch != '-' && ch != '(' && ch != ')') {
if (i < s.length() - 1) {
s1 += ch;
ch = s.charAt(++i);
} else if (i == s.length() - 1) {
s1 += ch;
i++;
}
if (i == s.length()) {
break;
}
}
if (s1 != "") {
stack2.push(Integer.parseInt(s1));
}
if (flag1 == 1 && ch == '(' ){
flag2++;
}
if (flag1 == 1 && flag2 == 0 && !stack1.empty()){
int eg = solve1(stack1.pop(), stack2.pop(), stack2.pop());
stack2.push(eg);
flag1 = 0;
}
if (ch == '+' || ch == '*' || ch == '(' || ch == '-') {
stack1.push(ch);
i++;
}
}
}
while (!stack1.empty() ) {
char eg1 = stack1.pop();
if (!stack1.empty() && stack1.peek() == '-') {
if (eg1 == '-')
eg1 = '+';
else
eg1 = '-';
}
int eg2 = solve1(eg1, stack2.pop(), stack2.pop());
stack2.push(eg2);
}
return stack2.pop();
}
}
二. 队列
java中用双向链表来实现队列,用单链表也可以实现队列,但是入队必须用尾插,出队必须用从头出
另外用顺序表也可以实现队列,但为了空间利用,用顺序表实现的是循环队列
循环队列需要解决两个问题,第一如何判断队列是满是空,第二如何实现数组满后对头和队尾在同一位置.(也就是如何从8位置到1位置)
Queue是一个接口,必须用LinkedList来实例化,因为LinkedList实现了Queue接口
1. 用数组模拟实现循环队列
需要注意的是,入队列时,队尾下标不能是单纯的加1;
出队列时,队头下标不能是单纯的加1;
访问队尾元素时,不能单纯的返回element[rear - 1], 而要判断当前队尾是否为0
import java.util.Arrays;
public class circularQueue {
private int[] element;
private int front = 0;
private int rear = 0;
public circularQueue(int i){
this.element = new int[i];
}
public boolean enQueue(int value){
if (isfull()){
this.element = Arrays.copyOf(this.element, 2 * this.element.length);
}
element[rear] = value;
rear = (rear + 1) % element.length;
return true;
}
public boolean deQueue(){
if (isEmpty()){
System.out.println("队列为空,不可出队");
return false;
}else{
this.front = (this.front + 1) % this.element.length;
return true;
}
}
public int Front(){
if (isEmpty()){
System.out.print("当前队列为空" + " ");
return -1;
}
return this.element[this.front];
}
public int Rear(){
if (isEmpty()){
System.out.print("当前队列为空" + " ");
return -1;
}
int index = this.rear == 0 ? this.element.length - 1 : this.rear - 1;
return this.element[index];
}
public boolean isfull(){
return ((this.rear + 1) % this.element.length == this.front);
}
public boolean isEmpty(){
return this.front == this.rear;
}
}
2. 双端队列
两端都可以进队或出队,此时的队列必须用双向链表来实现,java中的队列就是用双向链表来实现的
3. 刷题
3.1 用两个队列实现一个栈
需要注意的是入栈和获取栈顶元素时,将元素转移到空队列中时,for循环中的结束条件不能是queue.size(),因为在出队时size会发生变化,需用一个数来记录size值,这里出bug的几率极大
import java.util.LinkedList;
import java.util.Queue;
public class queue {
private Queue<Integer> queue1;
private Queue<Integer> queue2;
public queue(){
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
public void push(int valu){
if (!queue1.isEmpty()){
queue1.offer(valu);
}else if (!queue2.isEmpty()){
queue2.offer(valu);
}else{
queue1.offer(valu);
}
}
public int pop(){
if (!queue1.isEmpty()){
int length = queue1.size();
for(int i = 0; i < length - 1; i++){
queue2.offer(queue1.poll());
}
return queue1.poll();
}else if (!queue2.isEmpty()){
int length = queue2.size();
for(int i = 0; i < length - 1; i++){
queue1.offer(queue2.poll());
}
return queue2.poll();
}else{
System.out.print("当前栈为空, 出栈操作失败");
return -1;
}
}
public int peek(){
int eg = 0;
if (!queue1.isEmpty()){
int length = queue1.size();
for(int i = 0; i < length; i++){
eg = queue1.poll();
queue2.offer(eg);
}
return eg;
}else if (!queue2.isEmpty()){
int length = queue2.size();
for(int i = 0; i < length; i++){
eg = queue2.poll();
queue1.offer(eg);
}
return eg;
}else{
System.out.print("当前栈为空, 查询栈顶元素失败");
return -1;
}
}
public boolean empty(){
return queue1.isEmpty() && queue2.isEmpty();
}
}
3.2 用两个栈实现一个队列
import java.util.Stack;
public class MyQueue {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public MyQueue(){
stack1 = new Stack();
stack2 = new Stack();
}
public void offer(int valu){
stack1.push(valu);
}
public int poll(){
if(isEmply()){
System.out.print("当前队列为空,出队操作失败");
return -1;
}
if(stack2.empty()){
int length = stack1.size();
for(int i = 0; i < length; i++){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
public int peek(){
if(isEmply()){
System.out.print("当前队列为空,获取对尾元素操作失败");
return -1;
}
if(stack2.empty()){
int length = stack1.size();
for(int i = 0; i < length; i++){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
public boolean isEmply(){
return stack1.empty() && stack2.empty();
}
}