1.括號匹配問題
題目詳述: 有效的括號
解題思路
左括號入棧,右括號出戰,判斷是否匹配。
注意:
1.s = "}"
如果遍歷遍歷過程中,c 不是左括號時,先判斷棧是否爲空(爲空 return false
)。
2.s = "{"
遍歷完整個 s ,要判斷此時棧是否爲空(爲空 return true;
)。
程序測試
class Solution {
public boolean isValid(String s) {
//1.創建棧,保存字符類型
Stack<Character> stack = new Stack<>();
//2.循環遍歷整個字符串中的字符
for(int i = 0; i< s.length(); i ++){
char c = s.charAt(i);
//3.左括號入棧
if(c == '(' || c == '[' || c == '{'){ //注意:""爲字符串 ''爲字符
stack.push(c);
continue; //入棧完 直接對下一個字符判斷
}
if(stack.empty()){
return false; //s = ")" 不匹配 棧爲空
}
//4.右括號出棧
char top = stack.pop();
//5.判斷是否匹配
//合法情況1
if(top == '(' && c == ')'){
continue; //直接對下一個字符判斷
}
//合法情況2
if(top == '[' && c == ']'){
continue; //直接對下一個字符判斷
}
//合法情況3
if(top == '{' && c == '}'){
continue; //直接對下一個字符判斷
}
//不是上的的三種合法情況 則不合法
return false; // s = "([)]" 不合法
}
if(stack.empty()){
return true;
}
return false; // s = "{" 不合法 此時棧不爲空
}
}
2.合法括號序列判斷
題目詳述:合法括號序列判斷
解題思路
1.碰到")“開始彈出棧頂的”(",如果此時棧爲空,則返回false
2.碰到其他內容直接返回false
3.字符串結尾時,棧非空返回false
程序測試
import java.util.Stack;
public class Parenthesis {
public boolean chkParenthesis(String A, int n) {
Stack stack = new Stack();
for(int i = 0; i<n; i++){
if (A.charAt(i)!='(' && A.charAt(i)!=')'){ //排除其他字符的情況 (a)
return false;
}
if(A.charAt(i)=='('){
stack.push(A.charAt(i));
}
if(A.charAt(i)==')'){
if(stack.isEmpty()){ //排除左括號在前的情況 )()
return false;
}
stack.pop();
}
}
if(stack.isEmpty()){ //排除左括號過多的情況 (()
return true;
}
return false;
}
}
3.用隊列實現棧
題目詳述
鏈接:用隊列實現棧
思路解析
兩個隊列實現棧。
注意:
1.入棧:入 A 隊列。
2.出棧:將隊列 A 中的元素出隊列後入到隊列 B 中,A中的最後一個元素就是此時出棧元素。出棧完將 隊列 B 元素重新出隊列移回隊列 A。
程序測試
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class MyStackBy2Queue {
private Queue<Integer> A = new LinkedList<>();
private Queue<Integer> B = new LinkedList<>();
public void push(int x) {
// x 往 A 中入隊列即可
A.offer(x);
}
public Integer pop() {
if (empty()) {
return null;
}
// 把 A 中的元素往 B 中倒騰
while (A.size() > 1) {
Integer front = A.poll();
B.offer(front);
}
// 當循環結束之後, A 中應該就是 1 個元素;
// 這個元素就應該是被出棧的元素
int ret = A.poll();
// 交換 A 和 B 的身份
swapAB();
return ret;
}
private void swapAB() {
Queue<Integer> tmp = A;
A = B;
B = tmp;
// A = B;
// B.clear();
}
public Integer top() {
if (empty()) {
return null;
}
// 把 A 中的元素往 B 中倒騰
while (A.size() > 1) {
Integer front = A.poll();
B.offer(front);
}
// 當循環結束之後, A 中應該就是 1 個元素;
// 這個元素就應該是被出棧的元素
int ret = A.poll();
B.offer(ret); // top 和 pop 唯一的區別就是這句話
// 交換 A 和 B 的身份
swapAB();
return ret;
}
public boolean empty() {
return A.isEmpty() && B.isEmpty();
}
}
4.用棧實現隊列
題目詳述
鏈接:用棧實現隊列
思路解析
兩個棧實現隊列。
入隊列:入棧 A。
出隊列:將A中元素依次出棧再入到棧B,此時B出棧(B棧頂元素即爲返回的元素值),最後將B中的元素依次出棧在入到棧A。
程序測試
import java.util.Stack;
public class MyQueueBy2Stack {
private Stack<Integer> A = new Stack<>();
private Stack<Integer> B = new Stack<>();
public void push(int x) {
// 把新元素入 A 即可
A.push(x);
}
public Integer pop() {
// 1. 如果爲空, 就直接返回
if (empty()) {
return null;
}
// 2. 把 A 中的元素都倒騰給 B
while (!A.isEmpty()) {
B.push(A.pop());
}
// 3. 針對 B 進行出棧
int element = B.pop();
// 4. 再把 B 中的元素都倒騰到 A 裏
while (!B.isEmpty()) {
A.push(B.pop());
}
return element;
}
public Integer peek() {
// 1. 如果爲空, 就直接返回
if (empty()) {
return null;
}
// 2. 把 A 中的元素都倒騰給 B
while (!A.isEmpty()) {
B.push(A.pop());
}
// 3. 直接取 B 的棧頂元素
int element = B.peek();
// 4. 再把 B 中的元素都倒騰到 A 裏
while (!B.isEmpty()) {
A.push(B.pop());
}
return element;
}
public boolean empty() {
return A.isEmpty();
}
}
5.實現一個最小棧
題目詳述
鏈接:最小棧
思路解析
定義兩個棧A(正常棧)、B(最小棧)。
A:按正常棧的規則插入刪除元素。
B:存放的是當前棧的最小值(棧頂一定是當前最小值)。
注意:
1.入棧:先入 A ,後判斷是否入B。如果 B 爲空,直接入棧 B;B不爲空,將入棧元素與 B 的棧頂元素比較(若入棧元素小則將元素入棧 B,否則不入)。
2.出棧:將 A裏的元素正常出棧,B裏的棧頂元素刪除。
3.最小值:B 的棧頂元素。
程序測試
import java.util.Stack;
public class MinStack {
private Stack<Integer> A = new Stack<>();
private Stack<Integer> B = new Stack<>();
public void push(int x) {
A.push(x);
if (B.isEmpty()) {
B.push(x);
return;
}
int min = B.peek();
if (x < min) {
min = x;
}
B.push(min);
}
public Integer pop() {
if (A.isEmpty()) {
return null;
}
B.pop();
return A.pop();
}
public Integer top() {
if (A.isEmpty()) {
return null;
}
return A.peek();
}
public Integer getMin() {
if (B.isEmpty()) {
return null;
}
return B.peek();
}
}