- 用数组实现栈和队列
- 用栈实现队列
- 用队列实现栈
- 栈和队列的经典算法题
- 最小间距栈
- 宠物收养所
数组实现栈和队列
- 用数组实现栈:
- 创建一个类,包含一个数组和当前栈中存在的记录总数
- arr用于记录入栈元素, size记录当前的栈长度
代码如下:
// 用数组实现栈,实现增,删,查功能
static class ArrayStack{
int[] arr;
int size;
public ArrayStack(int capacity) {
this.arr = new int[capacity];
this.size = 0;
}
// 检查是否栈空
public boolean isEmpty() {
return this.size == 0;
}
// 检查是否栈满
public boolean isFull() {
return this.size == this.arr.length;
}
// 向栈中添加元素
public void push(int num) {
if (isFull()) {
throw new RuntimeException("stack is full");
}
arr[this.size++] = num;
}
// 从栈中弹出元素
public int pop() {
if (isEmpty()) {
throw new RuntimeException("stack is null");
}
return arr[--size];
}
// 查看栈顶元素
public int peek() {
if (isEmpty()) {
throw new RuntimeException("stack is null");
}
return arr[size - 1];
}
// 检查当前栈的大小
public int size(){
return this.size;
}
// toString()
@Override
public String toString() {
return "ArrayStack{" +
"arr=" + Arrays.toString(arr) +
", size=" + size +
'}';
}
- 用数组实现队列
- arr数组: 用于存放每次进入队列的元素
- size: 当前队列的存量
- start: 头指针,用于取出元素
- end:尾指针,用于添加元素
class ArrayQueue{
private Integer[] arr;
private Integer start;
private Integer end;
private Integer size;
public void ArrayStack(int initSize) {
if(initSize < 0) {
throw new IllegalArgumentException("The size is less on 0");
}
arr = new Integer[initSize];
start = 0;
end = 0;
size = 0;
}
// 入队列
public void push(Integer obj) {
if(isFull()) {
throw new ArrayIndexOutOfBoundsException("The queue is full!");
}
arr[end] = obj;
end = arr.length == end + 1 ? 0 : end + 1;
size++;
}
// 出队列
public Integer poll() {
if(isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The queue is empty!");
}
size--;
int temp = arr[start];
start = arr.length == start + 1 ? 0 : start + 1;
return temp;
}
// 弹出队列头
public Integer peek() {
if(isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The queue is empty!");
}
return arr[start];
}
// 检测队列是否为空
public boolean isEmpty(){
return size == 0;
}
// 检查队列是否已满
public boolean isFull() {
return size == arr.length;
}
栈实现队列
- 基本思路:(面试常考题))——leeCode232题
- 双栈实现队列(stack1 简称s1, stack2 简称s2)
- 添加元素时,只需要不停的向s1中添加元素即可
- 弹出队列头时,首先检测s2是否为空,如果为空,则把s1整体弹出压入s2,从而颠倒了入栈顺序,然后依次进行弹出即可
class MyQueue {
Stack s1;
Stack s2;
/** Initialize your data structure here. */
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
if (empty()) {
throw new RuntimeException("The queue is empty");
}
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
/** Get the front element. */
public int peek() {
if (empty()) {
throw new RuntimeException("The queue is empty");
}
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return s1.isEmpty() && s2.isEmpty();
}
}
队列实现栈
面试题 ———— leeCode225
- 创建两个队列q1和q2;
- 添加元素时,直接向q1里面扔
- 弹出元素时,首先将q1队列里面的元素依次出队列进入q2,直到q1里面只剩下一个元素,则将子元素弹出,然后q1和q1互换指引即可。
class MyStack {
Queue q1;
Queue q2;
/** Initialize your data structure here. */
public MyStack() {
q1 = new LinkedList<>();
q2 = new LinkedList<>();
}
/** Push element x onto stack. */
public void push(int x) {
q1.add(x);
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
if (empty()) {
throw new RuntimeException("The stack is empty");
}
while (q1.size() != 1) {
q2.add(q1.poll());
}
int ans = q1.poll();
swap();
return ans;
}
/** Get the top element. */
public int top() {
if (empty()) {
throw new RuntimeException("The stack is empty");
}
while (q1.size() != 1) {
q2.add(q1.poll());
}
int ans = q1.peek();
q2.add(q1.poll());
swap();
return ans;
}
/** Returns whether the stack is empty. */
public boolean empty() {
return q1.isEmpty();
}
/**Exchange q1 and q2.**/
public void swap() {
Queue temp = new LinkedList<>();
temp = q1;
q1 = q2;
q2 = temp;
}
}
队列和栈的应用
(leeCode155——最小栈 —— easy)
一、 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
要求:
1. pop\push\getMin操作的时间复杂度都是O(1)
2. 设计的栈可以使用现成的栈结构
基本思路:
- 创建两个栈(dataStack)存放数据, minStack(存放当前的最小值)
- push数据时,dataStack直接入栈,对于minStack, 如果栈空,或者当前的栈顶元素大于等于入栈元素,则minStack也入栈
- pop数据时,dataStack正常pop, minStack栈顶元素如果和当前pop的元素相等的时候,则minStack也需要pop
- 具体代码如下
class MinStack {
Stack dataStack; // 存放数据的栈
Stack minStack; // 存放当前最小值的栈
public MinStack() {
dataStack = new Stack();
minStack = new Stack();
}
// 数据入栈
public void push(int x) {
// 如果min栈空,直接入栈,否则比较大小,若小于等于,则入栈
if(minStack.isEmpty() || x <= minStack.peek()){
minStack.push(x);
}
dataStack.push(x);
}
// 数据出栈
public int pop(){
if(empty()){
throw new RuntimeException("The stack is empty");
}
// 如果当前dataStack栈顶元素和minStack栈顶元素相同,则同时出栈
int cur = dataStack.pop();
if(cur == minStack.peek()){
minStack.pop();
}
return cur;
}
// 获取当前的最小值
public int getMin() {
if(minStack.isEmpty()){
throw new RuntimeException("The stack is empty");
}
return minStack.peek();
}
// 判空
public boolean empty(){
return dataStack.isEmpty();
}
}
二、 宠物收养所(又名猫狗队列) ————lintCode230(hard)
在一个宠物避难所里,仅有狗和猫两种动物可供领养,且领养时严格执行“先进先出”的规则。
如果有人想要从避难所领养动物,他只有两种选择:要么选择领养所有动物中最资深的一只(根据到达避难所的时间,越早到的越资深),要么选择领养猫或狗(同样,也只能领养最资深的一只)。也就是说,领养者不能随意选择某一指定动物。请建立一个数据结构,使得它可以运行以上规则,并可实现 enqueue, dequeueAny, dequeueDog, 和 dequeueCat 操作。
解释:
enqueue: 猫或者狗入队列
dequeueAny: 按照添加的顺序出队列,不考虑猫狗属性
dequeueDog: 领养狗,弹出最后入队列的狗
dequeueCat: 领养猫,弹出最后入队列的猫
基本思路: 宠物队列由猫队列和狗队列组成,按照宠物属性分别加进不同的队列中,然后每次加入时都给宠物设置一个编号,编号越小,加入时间越早
// 创建宠物类
class Pet{
private String type;
// 构造器
public Pet(String type){
this.type = type;
}
public String getType() {
return type;
}
}
// 创建猫类
class Cat extends Pet{
public Cat() {
super("cat");
}
}
// 创建狗类
class Dog extends Pet{
public Dog() {
super("dog");
}
}
// 创建添加进入队列的对象
class EnterPet{
private Pet pet; // 入队列的对象
private long count; // 入队列对象的编号(编号越小,越早进入队列)
public EnterPet(Pet pet, long count) {
this.pet = pet;
this.count = count;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}
// 创建动物队列
class AnimalsQueue{
private Queue catQueue; // 猫队列
private Queue dogQueue; // 狗队列
private long count; // 记录队列总共接收的宠物总数
// 构造器
public AnimalsQueue(){
this.catQueue = new LinkedList();
this.dogQueue = new LinkedList();
this.count = 0;
}
// 宠物入队列
public void enQueue(Pet pet) {
if(pet.getType().equals("cat")){
catQueue.add(new EnterPet(pet,count++));
}else if(pet.getType().equals("dog")){
dogQueue.add(new EnterPet(pet,count++));
}else{
throw new RuntimeException("not dog or cat");
}
}
// 根据添加顺序出队列
public Pet deQueueAny(){
Pet pet = null;
// 猫狗队列都不为空
if(!dogQueue.isEmpty() && !catQueue.isEmpty()){
if(dogQueue.peek().getCount() < catQueue.peek().getCount()){
pet = dogQueue.poll().getPet();
}else{
pet = catQueue.poll().getPet();
}
}else if(!catQueue.isEmpty()){
pet = catQueue.poll().getPet();
}else if(!dogQueue.isEmpty()){
pet = dogQueue.poll().getPet();
}else{
throw new RuntimeException("Queue is empty");
}
return pet;
}
// 猫出队列
public Pet deQueueCat(){
if(catQueue.isEmpty()){
throw new RuntimeException("catQueue is empty");
}
return catQueue.poll().getPet();
}
// 狗出队列
public Pet deQueueDog(){
if(dogQueue.isEmpty()){
throw new RuntimeException("dogQueue is empty");
}
return dogQueue.poll().getPet();
}
// 查看是否还有宠物
public boolean isEmptyAll() {
return catQueue.isEmpty() && dogQueue.isEmpty();
}
// 查看是否还有猫
public boolean isEmptyCat() {
return catQueue.isEmpty();
}
// 查看是否还有狗
public boolean isEmptyDog() {
return dogQueue.isEmpty();
}
}+