算法练习 - 栈和队列(一)
文章目录
1 实现栈
1.1 基于数组
public class StackTest {
// 基于数组实现顺序栈
public class ArrayStack {
private int[] items; // 数组
private int count; // 元素个数
private int n; // 栈的大小
public ArrayStack(int n) {
this.items = new int[n];
this.count = 0;
this.n = n;
}
public boolean push(int item) {
if (count == n) {
// 栈已满,入栈失败
return false;
}
items[count] = item;
++count;
return true;
}
public int pop() {
if (count == 0) {
// 栈为空
return -1;
}
int value = items[count - 1];
--count;
return value;
}
public int peek() {
if (count == 0) {
// 栈为空
return -1;
}
return items[count - 1];
}
}
}
1.2 基于链表
由于在链表尾部进行插入和删除操作过于繁琐,所以采用头插
public class NodeStack {
public class Node {
public int data;
public Node next;
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
private Node head = null;
public void push(int value) {
Node newNode = new Node(value, null);
newNode.next = head;
head = newNode;
}
public int pop() {
if (head == null) {
return -1;
}
int value = head.data;
head = head.next;
return value;
}
public int peek() {
if (head == null) {
return -1;
}
return head.data;
}
}
2. 实现队列
2.1 基于数组(循环队列)
public class CQueue {
private String[] items;
private int n; // 队列的大小
private int head = 0;
private int tail = 0;
public CQueue(int n) {
this.items = new String[n];
this.n = n;
}
public boolean enqueue(String items) {
if ((tail + 1) % n == head) {
return false;
}
tail = (tail + 1) % n;
return true;
}
public String dequeue() {
if (head == tail) {
return null;
}
String result = items[head];
head = (head + 1) % n;
return result;
}
}
2.2 基于链表
public class LQueue {
private class Node {
public String data;
public Node next;
public Node(String data, Node next) {
this.data = data;
this.next = next;
}
private Node head = null;
private Node tail = null;
public void enqueue(String value) {
Node newNode = new Node(value, null);
if (tail == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
}
}
public String dequeue() {
if (head == null) {
return null;
}
String value = head.data;
head = head.next;
if (head == null) {
tail = null;
}
return value;
}
}
}
3. 剑指 Offer 09. 用两个栈实现队列
链接:https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof
3.1 题目
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
[“CQueue”,“appendTail”,“deleteHead”,“deleteHead”,“deleteHead”]
[[],[3],[],[],[]]
输出:[null,null,3,-1,-1]
示例 2:
输入:
[“CQueue”,“deleteHead”,“appendTail”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
3.2 题解
class CQueue {
private Stack<Integer> stack = new Stack<>();
private Stack<Integer> tmpStack = new Stack<>();
public CQueue() {
}
public void appendTail(int value) {
stack.push(value);
}
public int deleteHead() {
if (stack.isEmpty()) {
return -1;
}
while (!stack.isEmpty()) {
tmpStack.push(stack.pop());
}
int result = tmpStack.pop();
while (!tmpStack.isEmpty()) {
stack.push(tmpStack.pop());
}
return result;
}
}
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/
4. 用队列实现栈
链接:https://leetcode.cn/problems/implement-stack-using-queues
4.1 题目
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]
解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
4.2 题解
class MyStack {
Queue<Integer> queue = new LinkedList<>();
Queue<Integer> tmpQueue = new LinkedList<>();
public MyStack() {
}
public void push(int x) {
queue.offer(x);
while (!tmpQueue.isEmpty()) {
queue.offer(tmpQueue.poll());
}
Queue tmp = queue;
queue = tmpQueue;
tmpQueue = tmp;
}
public int pop() {
return tmpQueue.poll();
}
public int top() {
return tmpQueue.peek();
}
public boolean empty() {
return tmpQueue.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
5. 栈排序
链接:https://leetcode.cn/problems/sort-of-stacks-lcci
5.1 题目
栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作:push、pop、peek 和 isEmpty。当栈为空时,peek 返回 -1。
示例1:
输入:
[“SortedStack”, “push”, “push”, “peek”, “pop”, “peek”]
[[], [1], [2], [], [], []]
输出:
[null,null,null,1,null,2]
示例2:
输入:
[“SortedStack”, “pop”, “pop”, “push”, “pop”, “isEmpty”]
[[], [], [], [1], [], []]
输出:
[null,null,null,null,null,true]
说明:
栈中的元素数目在[0, 5000]范围内。
5.2 题解
class SortedStack {
Stack<Integer> stack = new Stack<>();
Stack<Integer> tmpStack = new Stack<>();
public SortedStack() {
}
public void push(int val) {
if (stack.isEmpty()) {
stack.push(val);
} else {
while (!stack.isEmpty() && val > stack.peek()) {
tmpStack.push(stack.pop());
}
stack.push(val);
while (!tmpStack.isEmpty()) {
stack.push(tmpStack.pop());
}
}
}
public void pop() {
if (!stack.isEmpty()) {
stack.pop();
} else {
return;
}
}
public int peek() {
if(!stack.isEmpty()) {
return stack.peek();
} else {
return -1;
}
}
public boolean isEmpty() {
return stack.isEmpty();
}
}
/**
* Your SortedStack object will be instantiated and called as such:
* SortedStack obj = new SortedStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.isEmpty();
*/
6. 三合一
链接:https://leetcode.cn/problems/three-in-one-lcci
6.1 题目
三合一。描述如何只用一个数组来实现三个栈。
你应该实现push(stackNum, value)、pop(stackNum)、isEmpty(stackNum)、peek(stackNum)方法。stackNum表示栈下标,value表示压入的值。
构造函数会传入一个stackSize参数,代表每个栈的大小。
示例1:
输入:
[“TripleInOne”, “push”, “push”, “pop”, “pop”, “pop”, “isEmpty”]
[[1], [0, 1], [0, 2], [0], [0], [0], [0]]
输出:
[null, null, null, 1, -1, -1, true]
说明:当栈为空时pop, peek
返回-1,当栈满时push
不压入元素。
示例2:
输入:
[“TripleInOne”, “push”, “push”, “push”, “pop”, “pop”, “pop”, “peek”]
[[2], [0, 1], [0, 2], [0, 3], [0], [0], [0], [0]]
输出:
[null, null, null, null, 2, 1, -1, -1]
6.2 题解
class TripleInOne {
private int[] array;
private int n;
private int[] top;
public TripleInOne(int stackSize) {
array = new int[3 * stackSize];
n = 3 * stackSize;
top = new int[3];
top[0] = -3;
top[1] = -2;
top[2] = -1;
}
public void push(int stackNum, int value) {
if (top[stackNum] + 3 >= n) {
return;
}
top[stackNum] += 3;
array[top[stackNum]] = value;
}
public int pop(int stackNum) {
if (top[stackNum] < 0) {
return -1;
}
int result = array[top[stackNum]];
top[stackNum] -= 3;
return result;
}
public int peek(int stackNum) {
if (top[stackNum] < 0) {
return -1;
}
return array[top[stackNum]];
}
public boolean isEmpty(int stackNum) {
return top[stackNum] < 0;
}
}
/**
* Your TripleInOne object will be instantiated and called as such:
* TripleInOne obj = new TripleInOne(stackSize);
* obj.push(stackNum,value);
* int param_2 = obj.pop(stackNum);
* int param_3 = obj.peek(stackNum);
* boolean param_4 = obj.isEmpty(stackNum);
*/
7. 有效的括号
链接:https://leetcode.cn/problems/valid-parentheses
7.1 题目
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
7.2 题解
class Solution {
Stack<Character> stack = new Stack<>();
public boolean isValid(String s) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (compare(c)) {
stack.push(c);
} else {
int result = sen(c);
if (result == 0) {
return false;
}
}
}
return stack.isEmpty();
}
public boolean compare(char c) {
if (c == '(' || c == '{' || c == '[') {
return true;
} else {
return false;
}
}
public int sen(char c) {
if (stack.isEmpty()) {
return 0;
} else {
char ch = stack.peek();
if (c == ')' && ch == '(' || c == '}' && ch == '{' || c == ']' && ch == '[') {
stack.pop();
return 1;
} else {
return 0;
}
}
}
}