代码随想录算法训练营Day10|栈与队列part01

108 阅读4分钟

理论基础

Java Stack类

The Stack class extends class Vector, representing s LIFO(last-in-first-out) stack of objects.

Constructor

Stack<E> st = new Stack<E>();    // creates an empty stack

Methods

  • public boolean empty()当且仅当栈中没有元素时返回true
  • public E peek() 返回栈顶元素
  • public E pop() 移除栈顶元素并返回
  • public E push(E item) 把item元素添加到栈顶
  • public int search(Object o) 返回o在栈中的位置(有多个则为最小的位置),栈顶元素为1,不存在则返回-1

Java Queue接口

Queues order elements in a FIFO(first-in-first-out) manner. Queue接口常用的两个实现:PriorityQueue类,LinkedList类

Methods

  • boolean add(E e) 如果有空间就插入元素e,返回true,没有空闲空间则抛出IllegalStateException异常
  • boolean offer(E e) 如果有空间就插入元素e,返回true;否则返回false,注意与add方法的区别
  • E element() 获取队列头,但不移除;如果队列为空,抛出NoSuchElementException
  • E peek() 获取队列头,但不移除;如果队列为空,返回null
  • E remove() 获取并移除队列头,若队列为空则抛出IllegalStateException异常
  • E poll() 获取并移除队列头,若队列为空返回null

LeetCode 232 用栈实现队列

题目链接:leetcode.cn/problems/im…

文档讲解:programmercarl.com/0232.用栈实现队列…

视频讲解:www.bilibili.com/video/BV1nY…

思路

栈是单侧出入,队列是两侧出入。故我们使用两个栈模拟队列。 栈的行为是先进后出,队列的行为是先进先出。 考虑两个栈stackA和stackB如何模拟队列行为:

  1. 两个栈初始为空
  2. 元素e入队
    1. 元素e入栈stackA
  3. 元素e出队(此时应该让stackA中栈底的元素出栈)
    1. 如果stackB为空
      1. 依次对stackA中所有元素先出栈,后入栈stackB(那么B中元素的出栈顺序就和这些元素入栈A时相同,完成了先进先出的模拟)
      2. stackB.pop
    2. 如果B不空则直接pop

解法

class MyQueue {
	private Stack<Integer> stackA;
	private Stack<Integer> stackB;
	public MyQueue() {
		stackA = new Stack<>();
		stackB = new Stack<>();
	}
	
	public void push(int x) {
		stackA.push(x);
	}
	
	public int pop() {
		if (stackB.empty()) {
			while (!stackA.empty()) {
				int e = stackA.pop();
				stackB.push(e);
			}
		}
		return stackB.pop();
	}
	
	public int peek() {
	
		if (stackB.empty()) {
			while (!stackA.empty()) {
				int e = stackA.pop();
				stackB.push(e);
			}
		}
		return stackB.peek();
	
	}
	
	public boolean empty() {
		return stackA.empty() && stackB.empty();
	}

}

LeetCode 225 用队列实现栈

题目链接:leetcode.cn/problems/im…

文档讲解:programmercarl.com/0225.用队列实现栈…

视频讲解:www.bilibili.com/video/BV1Fd…

思路

考虑用队列的标准操作模拟栈的操作:

  1. 元素入栈:
    1. 元素入队
  2. 元素出栈:(需要把队尾的元素出队)
    1. 队列中有n个元素,把前n-1个元素出队保存起来,第n个元素出队返回
    2. 具体如何保存:可以放入另一个队列or直接再次入队
  3. 获取栈顶元素:
    1. 队列中有n个元素,把前n-1个元素出队后入队,第n个元素读取后也入队

解法

class MyStack {

	private Queue<Integer> queue;
	
	public MyStack() {
		queue = new LinkedList<>();

	}
	
	public void push(int x) {
		queue.offer(x);
	}
	
	public int pop() {
		int n = queue.size();
		for (int i = 0; i < n-1; i++) {
			int e = queue.poll();	
			queue.offer(e);
		}
		return queue.poll();
	}
	
	public int top() {
		int n = queue.size();
		for (int i = 0; i < n-1; i++) {
			int e = queue.poll();
			queue.offer(e);
		}
		int result = queue.poll();
		queue.offer(result);
		return result;
	}
	
	public boolean empty() {
		return queue.isEmpty();
	}

}

LeetCode 20 有效的括号

题目链接:leetcode.cn/problems/va…

文档讲解:programmercarl.com/0020.有效的括号.…

视频讲解:www.bilibili.com/video/BV1AF…

思路

很经典的用栈解决的题目

  1. 当栈空,括号入栈
  2. 当栈顶括号和现在的括号可以左右匹配,栈顶括号出栈
  3. 不可以匹配则括号入栈
  4. 当字符串被遍历完,如果栈空,则有效;否则无效

解法

class Solution {
	public boolean isValid(String s) {
		Stack<Character> stack = new Stack<>();
		for (int i = 0; i < s.length(); i++) {
			if (stack.empty()) {
				stack.push(s.charAt(i));
			}
			else if (match(stack.peek(), s.charAt(i))) {
				stack.pop();
			}
			else {
				stack.push(s.charAt(i));
			}
		}
		if (stack.empty()) {
			return true;
		}
		return false;
	}

	private boolean match(char i, char j) {
		if (i == '(' && j==')') {
			return true;
		}
		if (i == '[' && j==']') {
			return true;
		}
		if (i == '{' && j=='}') {
			return true;
		}
		
		return false;
	
	}

}

LeetCode 1047 删除字符串中所有的相邻重复项

题目链接:leetcode.cn/problems/re…

文档讲解:programmercarl.com/1047.删除字符串中…

视频讲解:www.bilibili.com/video/BV12a…

思路

相邻重复项的性质和上题括号相似,对字符串中每个字符遍历

  1. 当栈空,字符入栈
  2. 当栈顶字符与当前字符相同,栈顶字符出栈
  3. 否则,字符入栈
  4. 遍历完成后,返回栈中剩余的字符组成的字符串

解法

class Solution {
	public String removeDuplicates(String s) {
		Stack<Character> stack = new Stack<>();
		for (int i = 0; i < s.length(); i++) {
			char ch = s.charAt(i);
			if (stack.empty()) {
				stack.push(ch);
			}
			
			else if (stack.peek() == ch) {
				stack.pop();
			}
			
			else {
				stack.push(ch);
			}
		}
		char[] charArr = new char[stack.size()];
		for (int i = charArr.length-1; i >= 0; i--) {
			charArr[i] = stack.pop();
		}
		return new String(charArr);
	
	}

}

今日收获总结

今日学习2.5小时,第二次刷,栈的掌握还算比较好,题目更典型