目录
检查括号是否成对出现
反转字符串
循环队列的实现
使用队列实现栈
使用栈实现队列
检查括号是否成对出现
算法要求
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断该字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
比如: "()"、"()[]{}"、"{[]}" 都是有效字符串,而 "(]" 、"([)]" 则不是
解题思路
1、我们可以通过一个HashMap来存放所有括号类型,右括号为键,左括号为值。
2、遍历字符串,如果是左括号就入栈,右括号则和栈顶元素作比较,如果刚好形成一对完成括号,则继续。否则说明不是一对完整括号。
3、遍历结束后判断栈中元素是否全部取出,只有全部取出,说明这个字符串中符号成对出现。
/**
* 判断这个符号字符串中符号是否成对出现
* @param s
* @return
*/
public static boolean isValid(String s){
//创建一个hashMap把所有符号都存入
Map<Character,Character> maps =new HashMap<>();
maps.put(')','(');
maps.put(']','[');
maps.put('}','{');
Stack<Character> stack =new Stack<>();
//将字符串转换为字符数组
char[] chars= s.toCharArray();
//遍历字符数组
for (int i = 0; i <chars.length ; i++) {
//判断这个符号是否为右括号
if (maps.containsKey(chars[i])){
//栈中如果为空赋值为#否则取出栈顶元素
char isEmpty =stack.isEmpty()?'#':stack.pop();
//判断这个右括号对应的左括号是否等于栈顶元素
if (isEmpty!=maps.get(chars[i])){
return false;
}
}else {
//如果为左括号则入栈
stack.push(chars[i]);
}
}
//遍历结束 如果栈中还有元素 则说明其中没有对应括号
return stack.isEmpty();
}
测试
public static void main(String[] args) {
System.out.println("[]{}()中符号是否成对出现:"+isValid("[]{}()"));
System.out.println("{([})}中符号是否成对出现:"+isValid("{([])}"));
System.out.println("([)]中符号是否成对出现:"+isValid("([)]"));
System.out.println("(()中符号是否成对出现:"+isValid("(()"));
}
测试结果
反转字符串
这个就直接运用栈的后进先出原则,把字符串依次入栈再出栈就行。
/**
* 字符串的反转
* @param s
* @return
*/
public static String stringReversal(String s){
Stack<Character> stack =new Stack<>();
for (int i =0;i<s.length();i++){
stack.push(s.charAt(i));
}
String news="";
for (int i = 0, len = stack.size(); i < len; i++) {
news+=stack.pop();
}
return news;
}
测试
public static void main(String[] args) {
String ts ="the shy";
String yskm ="you should know me";
System.out.println("ts反转前:"+ts);
System.out.println("ts反转后:"+stringReversal(ts));
System.out.println("yskm反转前:"+yskm);
System.out.println("yskm反转后:"+stringReversal(yskm));
}
测试结果
循环队列的实现
和队列相比,循环队列的优点就是不会造成假溢出,因为当队尾到达数组的末尾时,如果数组头部还有空间,则会继续向头部移动。会形成一个循环,除非队尾与队头相邻,则队列才满。
/**
* 循环队列的实现
* @author CC
* @version 1.0
* @since2023/9/28
*/
public class CircularQueue {
private int[] array;//使用数组来存储
private int front;//对头
private int rear;//队尾
//实例队列并设置初始容量
public CircularQueue(int capacity){
this.array =new int[capacity];
}
/**
* 入队
* @param element
* @throws Exception
*/
public void offer(int element) throws Exception {
//队尾不能存值 所以队尾的下一个元素如果是队头 说明队列已满
if ((rear+1)%array.length==front){
throw new Exception("队列已满!");
}
//将值存入队尾
array[rear] =element;
//队尾向后移动
rear =(rear+1)%array.length;
}
/**
* 出队
* @return
* @throws Exception
*/
public int pull() throws Exception {
//如果队头等于队尾 则只有一个可能 就是该队为空
if (rear==front){
throw new Exception("队列为空!");
}
//取出队头元素
int deQueueElement =array[front];
//队头向后移动
front=(front+1)%array.length;
return deQueueElement;
}
/**
* 输出队列
* @return
*/
@Override
public String toString() {
StringJoiner sj =new StringJoiner("-");
for (int i=front;i!=rear;i=(i+1)%array.length){
sj.add(String.valueOf(array[i]));
}
return sj.toString()+"-队尾";
}
}
测试
/**
* @author CC
* @version 1.0
* @since2023/9/28
*/
public class CTest {
public static void main(String[] args) throws Exception {
CircularQueue queue = new CircularQueue(5);
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
System.out.println("接连将1、2、3、4分别入队后:"+queue);
queue.pull();
System.out.println("发生一次出队后:"+queue);
queue.offer(5);
System.out.println("将5入队后:"+queue);
}
}
测试结果
使用队列实现栈
实现原理
通过创建两个队列,一个为出栈队列,一个为入栈队列。首先入栈队列是一直为空的,在入栈时先将元素存入入栈队列,再将出栈队列的元素依次存入入栈队列,这就将刚入元素就被放入了队尾。然后交换两个队列,出栈时将出栈队列队头元素出栈,也就是最早入栈的元素。
/**
* @author CC
* @version 1.0
* @since2023/9/30
*/
public class MyStack {
private Queue<Integer> queue1; //出栈队列
private Queue<Integer> queue2; //入栈队列
/**
* 初始化栈 底层使用链表存储
*/
public MyStack() {
queue1 = new LinkedList<Integer>();
queue2 = new LinkedList<Integer>();
}
/**
* 入栈
* @param item
*/
public void push(int item) {
//将元素存入队列2
queue2.offer(item);
//将队列1中元素依次出队 并存入队列2
while (!queue1.isEmpty()){
queue2.offer(queue1.poll());
}
//交换队列1 与 队列2
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
/**
* 出栈
* @return
*/
public int pop(){
return queue1.poll();
}
/**
* 获取栈顶元素
* @return
*/
public int top(){
return queue1.peek();
}
/**
* 判断该栈是否为空
* @return
*/
public boolean isEmpty(){
return queue1.isEmpty();
}
/**
* 输出栈中元素
* @return
*/
@Override
public String toString() {
StringJoiner sj =new StringJoiner("-");
for (Integer integer : queue1) {
sj.add(String.valueOf(integer));
}
return "栈顶"+sj.toString();
}
}
测试
/**
* @author CC
* @version 1.0
* @since2023/9/30
*/
public class MyStackT {
public static void main(String[] args) {
MyStack stack =new MyStack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println("1、2、3、4依次入栈后:"+stack);
System.out.println("出栈元素:"+stack.pop());
System.out.println("出栈一次后:"+stack);
System.out.println("查看栈顶元素(不取出):"+stack.top());
System.out.println("查看栈顶元素后:"+stack);
System.out.println("该栈是否为空:"+stack.isEmpty());
System.out.println("出栈元素:"+stack.pop());
System.out.println("出栈元素:"+stack.pop());
System.out.println("出栈元素:"+stack.pop());
System.out.println("该栈是否为空:"+stack.isEmpty());
}
}
测试结果
使用栈实现队列
实现原理
创建两个栈,一个为入队栈、一个为出队栈。入队栈的出栈顺序为后进先出。因为出队时,需要把入队栈的元素依次出栈再入栈到出队栈。后进先出的后进先出就为先进先出。所以出队栈的出栈顺序为先进先出。以此来实现和队列相同逻辑,先进先出。
/**
* @author CC
* @version 1.0
* @since2023/9/30
*/
public class MyQueue {
private Stack<Integer> inStack =new Stack<>(); //入队栈
private Stack<Integer> outStack =new Stack<>(); //出队栈
/**
* 入队
* @param item
*/
public void offer(int item){
//将出堆栈中的元素依次放入入队栈中
while (!outStack.isEmpty()){
inStack.push(outStack.pop());
}
//入队栈入栈
inStack.push(item);
}
/**
* 出队
* @return
*/
public int poll(){
//将入堆栈中的元素依次放入出队栈中
while (!inStack.isEmpty()){
outStack.push(inStack.pop());
}
//出堆栈出栈
return outStack.pop();
}
/**
* 判断队中是否为空
* @return
*/
public boolean isEmpty(){
return inStack.isEmpty()&outStack.isEmpty();
}
/**
* 查看队列元素
* @return
*/
@Override
public String toString() {
while (!inStack.isEmpty()){
outStack.push(inStack.pop());
}
StringJoiner sj =new StringJoiner("-");
for (Integer integer : outStack) {
sj.add(integer.toString());
}
return "队尾-"+sj.toString();
}
}
测试
public class MyQueueT {
public static void main(String[] args) {
MyQueue myQueue =new MyQueue();
// 入队
myQueue.offer(1);
myQueue.offer(2);
myQueue.offer(3);
myQueue.offer(4);
myQueue.offer(5);
System.out.println("依次入队1、2、3、4、5后:"+myQueue);
// 出队
System.out.println("出队:"+myQueue.poll()); // 1
System.out.println("出队:"+myQueue.poll()); // 2
System.out.println("出队:"+myQueue.poll()); // 3
System.out.println("连续三次出队后:"+myQueue);
// 入队
myQueue.offer(6);
myQueue.offer(7);
myQueue.offer(8);
System.out.println("依次入队6、7、8后:"+myQueue);
// 出队
System.out.println("出队:"+myQueue.poll()); // 4
System.out.println("出队:"+myQueue.poll()); // 5
System.out.println("出队:"+myQueue.poll()); // 6
System.out.println("连续三次出队后:"+myQueue);
System.out.println("队内是否为空:"+myQueue.isEmpty());
System.out.println("出队:"+myQueue.poll()); // 7
System.out.println("出队:"+myQueue.poll()); // 8
System.out.println("队内是否为空:"+myQueue.isEmpty());
}
}
测试结果