日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构栈和队列以及常见算法题

發布時間:2023/12/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构栈和队列以及常见算法题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概念:一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數據元素遵守后進先出LIFO(Last In First Out)的原則。
壓棧:棧的插入操作叫做進棧/壓棧/入棧,入數據在棧頂。
出棧:棧的刪除操作叫做出棧。出數據在棧頂。

數據結構的棧和jvm運行時內存區域中的stack是啥關系:
方法的調用涉及到棧幀,調用一個方法就壓棧,方法執行完就出棧。棧幀中有局部變量表,局部變量表存放的是方法調用過程中的局部變量。

操作:

import java.util.Deque; import java.util.LinkedList; import java.util.Stack;//如何實現棧 public class StackDemo {public static void main(String[] args) {//使用stack // Stack<String> stack = new Stack<>(); // // stack.push("A"); // stack.push("B"); // stack.push("C"); // // System.out.println(stack.size()); // 3 // System.out.println(stack.isEmpty()); // false // System.out.println(stack.empty()); // false // System.out.println(stack); // // System.out.println(stack.peek()); // C // System.out.println(stack.peek()); // C // System.out.println(stack.pop()); // C // System.out.println(stack.pop()); // B//使用DequeDeque<String> stack = new LinkedList<>();stack.push("A");stack.push("B");stack.push("C");System.out.println(stack);System.out.println(stack.isEmpty()); // falseSystem.out.println(stack.size()); // 3System.out.println(stack.peek()); // CSystem.out.println(stack.peek()); // CSystem.out.println(stack.pop()); // CSystem.out.println(stack.pop()); // B} }

題目20:有效的括號

根據括號的匹配原則,選擇數據結構為棧。
創建一個空棧,存儲內容為字符,將字符串轉化為字符數組;
遍歷字符數組,如果是左括號就入棧,如果是右括號

  • 如果棧為空,直接返回false
  • 彈出棧頂元素看是否匹配,不匹配就直接返回false;匹配就繼續遍歷下一個字符
public boolean isValid(String s) {Stack<Character> stack = new Stack<>();char [] chars = s.toCharArray();for (char ch : chars){if (ch == '(' || ch == '[' || ch == '{'){stack.push(ch);}else {if (stack.empty()){return false;}char left = stack.pop();if (left == '(' && ch == ')'){continue;}else if (left == '[' && ch == ']'){continue;}else if (left == '{' && ch == '}'){continue;}else {return false;}}}return stack.empty();}

題目:劍指offer31棧的壓入,彈出序列

private List<Integer> arrayToList(int []array){List<Integer> list = new ArrayList<>(array.length);for (int e: array){list.add(e);}return list;}public boolean validateStackSequences(int[] pushed, int[] popped) {List<Integer> pushedList = arrayToList(pushed);List<Integer> popedList = arrayToList(popped);Stack<Integer> stack = new Stack<>();for (int e : pushedList){if (!stack.isEmpty() && stack.peek() == e){stack.pop();continue;}while (true) {if (pushedList.isEmpty()) {return false;}int f = pushedList.remove(0);if (f != e) {stack.push(f);} else {break;}}}return stack.isEmpty();}

題目225:用兩個隊列實現棧

方法一:
push:
1.選擇一個隊列(哪個隊列中有數據選哪個,都沒有就指定一個)
2.把元素加入隊列中
pop:
1.選擇一個隊列(有數據的隊列)
2.把該隊列中的size - 1個數據移動到另一個隊列中
3.把隊列剩余的元素出掉
top:
1.選擇一個隊列(有數據的那個隊列)
2.把該隊列中的size-1個數據移動到另一個隊列中
3.把隊列剩余的返回,并且把該元素放入另一個隊列中
方法二:
還有一種方法不必使用到兩個隊列,使用一個隊列即可,先將所有元素入隊列,如果要取元素就把前size-1個個元素又放回隊列,將最后一個出隊列,依次這樣操作。
方法一的實現:

class MyStack {private Queue<Integer> queue1 = new LinkedList<>();private Queue<Integer> queue2 = new LinkedList<>();/** Initialize your data structure here. */public MyStack() {}/** Push element x onto stack. */public void push(int x) {Queue<Integer> queue;if (!queue1.isEmpty()) {queue = queue1;} else if (!queue2.isEmpty()) {queue = queue2;} else {queue = queue1;}queue.add(x);}/** Removes the element on top of the stack and returns that element. */public int pop() {Queue<Integer> queue;Queue<Integer> toQueue;if (!queue1.isEmpty()) {queue = queue1;toQueue = queue2;} else {queue = queue2;toQueue = queue1;}int size = queue.size();for (int i = 0; i < size - 1; i++) {int e = queue.remove();toQueue.add(e);}return queue.remove();}/** Get the top element. */public int top() {Queue<Integer> queue;Queue<Integer> toQueue;if (!queue1.isEmpty()) {queue = queue1;toQueue = queue2;} else {queue = queue2;toQueue = queue1;}int size = queue.size();for (int i = 0; i < size - 1; i++) {int e = queue.remove();toQueue.add(e);}int f = queue.remove();toQueue.add(f);return f;}/** Returns whether the stack is empty. */public boolean empty() {return queue1.isEmpty() && queue2.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();*/

題目155:最小棧

本題要求的時間復雜度是O(1),push操作個peek操作原本就是O(1),獲取棧中的最小元素,要么是遍歷棧的元素得出最小元素,要么就是創建一個遍歷記錄,這里我們使用一個棧來進行記錄,這樣做的好處是利用了入棧和出棧O(1)的時間復雜度。

push :val入棧普通棧;最小棧:如果val<=最小棧的棧頂元素,那么該元素也入棧最小棧。
為什么這里是<=呢?很多人可能會疑問,如果等于此時最小棧的棧頂元素,那么最小值不是已經在最小棧中存在了嗎,為什么還要入棧?因為我們忽略了一種特殊情況:

pop:普通棧出棧x,如果x==最小棧的棧頂元素那么最小棧才出棧。

class MinStack {//正確private Stack<Integer> normal = new Stack<>();private Stack<Integer> min = new Stack<>();/** initialize your data structure here. */public MinStack() {}public void push(int val) {normal.push(val);if (min.isEmpty() || val <= min.peek()) {min.push(val);} else {min.push(min.peek());}}public void pop() {normal.pop();min.pop();}public int top() {return normal.peek();}public int getMin() {return min.peek();} }

隊列

概念:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表,具有先進先出的特點。
入隊列:進行插入操作的一端稱為隊尾(Tail/Rear)
出隊列:進行刪除操作的一端稱為隊頭(Head/Front)
尾插頭刪
操作:

import java.util.LinkedList; import java.util.Queue;public class QueneDemo {public static void main(String[] args) {Queue<String> queue = new LinkedList<>();queue.add("A");queue.add("B");queue.add("B");System.out.println(queue.isEmpty()); //判斷隊列是否為空System.out.println(queue.size()); //隊列的大小System.out.println(queue.remove()); //出隊System.out.println(queue.element()); //查看隊首元素} }

題目232:用棧實現隊列


push:將數據放入棧2
pop:如果1號棧空了,把二號棧的所有元素放到一號棧,從棧1出數據
peek:如果棧1中有數據,直接從棧1中取數據,如果棧1沒有數據,棧2中有數據就去將棧2中的所有元素放入棧1再從棧1取數據

class MyQueue {private Stack<Integer> stack1 = new Stack<>();private Stack<Integer> stack2 = new Stack<>();/** Initialize your data structure here. */public MyQueue() {}/** Push element x to the back of queue.* 將元素 x 推到隊列的末尾 */public void push(int x) {stack2.push(x);}/** Removes the element from in front of queue and returns that element.* 從隊列的開頭移除并返回元素*/public int pop() {if (stack1.isEmpty()) {// 把 stack2 的全部數據移入 stack1 // int size = stack2.size(); // for (int i = 0; i < size; i++) { // int e = stack2.pop(); // stack1.push(e); // }while (!stack2.isEmpty()) {int e = stack2.pop();stack1.push(e);}}return stack1.pop();}/** Get the front element.* 返回隊列開頭的元素*/public int peek() {if (stack1.isEmpty()) {while (!stack2.isEmpty()) {int e = stack2.pop();stack1.push(e);}}return stack1.peek();}/** Returns whether the queue is empty.* 如果隊列為空,返回 true ;否則,返回 false*/public boolean empty() {return stack1.isEmpty() && stack2.isEmpty();} }

題目622:設計循環隊列



但是rear==front的時候無法判斷隊列是空還是滿。
為了達到判斷循環隊列滿的條件,犧牲一個空間。

取隊首元素:array[frontIndex]
取隊尾元素:array[(rearIndex - 1 + array.length) % array.length]

隊滿:(rearIndex+1)%array.length == frontIndex
隊空:rearIndex = = frontIndex

class MyCircularQueue {private int[] array;private int frontIndex;private int rearIndex;private int size;public MyCircularQueue(int k) {array = new int[k];frontIndex = 0;rearIndex = 0;size = 0;}//插入public boolean enQueue(int value) {if (isFull()) {return false;}array[rearIndex] = value;rearIndex = (rearIndex + 1) % array.length;size++;return true;}//刪除public boolean deQueue() {if (isEmpty()) {return false;}frontIndex = (frontIndex + 1) % array.length;size--;return true;}//取隊首public int Front() {if (isEmpty()) {return -1;}return array[frontIndex];}//public int Rear() {if (isEmpty()) {return -1;}int index = (rearIndex - 1 + array.length) % array.length;return array[index];}public boolean isEmpty() {return size == 0;}public boolean isFull() {return size == array.length;} }

總結

以上是生活随笔為你收集整理的数据结构栈和队列以及常见算法题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。