代碼隨想錄_棧與隊列

棧與隊列

232.用棧實現隊列

232. 用棧實現隊列

使用棧實現隊列的下列操作:

push(x) – 將一個元素放入隊列的尾部。
pop() – 從隊列首部移除元素。
peek() – 返回隊列首部的元素。
empty() – 返回隊列是否為空。

思路: 定義兩個棧: 入隊棧, 出隊棧, 控制出入棧順序, 進入的元素倒兩次就是原順序

代碼:

class MyQueue {Stack<Integer> in;Stack<Integer> out;public MyQueue() {in = new Stack<>();out = new Stack<>();}public void push(int x) {in.push(x);}public int pop() {inToOut();return out.pop();}public int peek() {inToOut();return out.peek();}private void inToOut() {// out非空時不能往里面倒, 出的時候要先把out里的出完, 再倒入// 否則原來的數據會被覆蓋if(!out.isEmpty()) return;while(!in.isEmpty()) {out.push(in.pop());}}public boolean empty() {return in.isEmpty() && out.isEmpty();}
}

225. 用隊列實現棧

225. 用隊列實現棧

使用隊列實現棧的下列操作:

  • push(x) – 元素 x 入棧
  • pop() – 移除棧頂元素
  • top() – 獲取棧頂元素
  • empty() – 返回棧是否為空

思路: 每次pop, peek都要reposition

代碼:

class MyStack {Queue<Integer> queue;public MyStack() {queue = new LinkedList<>();}public void push(int x) {queue.offer(x);}public int pop() {reposition();// 每次pop時將隊列前size - 1個放到隊列末尾return queue.poll();}public int top() {reposition();// 每次pop時將隊列前size - 1個放到隊列末尾int n = queue.poll();queue.offer(n);return n;}public boolean empty() {return queue.isEmpty();}private void reposition() {int size = queue.size();size--;while(size-- > 0) {queue.offer(queue.poll());}}
}

20. 有效的括號

20. 有效的括號

給定一個只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串,判斷字符串是否有效。

有效字符串需滿足:

  • 左括號必須用相同類型的右括號閉合。
  • 左括號必須以正確的順序閉合。
  • 注意空字符串可被認為是有效字符串。

思路:

一共有三種情況:

  • 字符串里左方向的括號多余了 ,所以不匹配。

  • 括號沒有多余,但是 括號的類型沒有匹配上。

  • 字符串里右方向的括號多余了,所以不匹配。

    每一個左括號, 壓入對應的右括號, 當開始遍歷右括號時, 按照如下方式和棧中元素進行對比

代碼:

class Solution {public boolean isValid(String s) {// 0. 剪枝int len = s.length();if(len % 2 != 0) return false;// 長度為奇數, 則一定不能匹配// 1. 初始化棧Stack<Character> stack = new Stack<>();// 2. 遍歷每一個字符for(int i = 0;i < len;i++) {// 2.1 每一個左括號, 壓入對應的右括號if(s.charAt(i) == '(') {stack.push(')');}else if(s.charAt(i) == '[') {stack.push(']');}else if(s.charAt(i) == '{') {stack.push('}');// 2.2 每一個右括號, 查看棧中對應的右括號是否相等}else if(stack.isEmpty() || s.charAt(i) != stack.peek()) {// 不能是s.pop,否則在判斷時就會將元素彈出return false;}else {// 右括號匹配, 出棧stack.pop();}}// 3. 遍歷完后, 查看棧中是否還有右括號(左括號多余)return stack.isEmpty();}
}

1047. 刪除字符串中的所有相鄰重復項

1047. 刪除字符串中的所有相鄰重復項

給出由小寫字母組成的字符串 S,重復項刪除操作會選擇兩個相鄰且相同的字母,并刪除它們。

在 S 上反復執行重復項刪除操作,直到無法繼續刪除。

在完成所有重復項刪除操作后返回最終的字符串。答案保證唯一。

示例:

  • 輸入:“abbaca”
  • 輸出:“ca”
  • 解釋:例如,在 “abbaca” 中,我們可以刪除 “bb” 由于兩字母相鄰且相同,這是此時唯一可以執行刪除操作的重復項。之后我們得到字符串 “aaca”,其中又只有 “aa” 可以執行重復項刪除操作,所以最后的字符串為 “ca”。

法一: 棧

思路: 用字符串模擬棧(也可以直接用棧, 需要再轉為字符串)進行"消消樂", 留下的就是最終的字符串

代碼:

class Solution {public String removeDuplicates(String s) {// 1. 定義字符串模擬棧StringBuilder sb = new StringBuilder();// 2. 遍歷s的每一位, 與棧進行消除int top = -1;for(int i = 0;i < s.length();i++) {if(top >= 0 && s.charAt(i) == sb.charAt(top)) {sb.deleteCharAt(top--);}else {sb.append(s.charAt(i));top++;}}// 3. 返回return sb.toString();}
}

法二:雙指針

思路: 快指針指向原字符串要處理的字符, 慢指針指向新的字符串, 當新字符串出現相鄰相等的情況, 則將兩個同時排除, 回退到第一次出現該字符的位置, 繼續遍歷原字符串的下一個字符, 否則, 快慢指針同時往前走.

代碼:

class Solution {public String removeDuplicates(String s) {// 1. 初始化char[] str = s.toCharArray();int fast = 0,slow = 0;// 2. 遍歷原字符串while(fast < str.length) {str[slow] = str[fast++];// 2.1 新的字符串出現成對可消除, 走到第一次出現的位置, 覆蓋(同時消除)if(slow > 0 && str[slow] == str[slow - 1]) {slow--;}else{// 2.2 沒有可消除的字符, fast slow都往后走slow++;}}// 3. 返回return new String(str,0,slow);}
}

150. 逆波蘭表達式求值

150. 逆波蘭表達式求值

根據 逆波蘭表示法,求表達式的值。

有效的運算符包括 + , - , * , / 。每個運算對象可以是整數,也可以是另一個逆波蘭表達式。

說明:

整數除法只保留整數部分。 給定逆波蘭表達式總是有效的。換句話說,表達式總會得出有效數值且不存在除數為 0 的情況。

示例 1:

  • 輸入: [“2”, “1”, “+”, “3”, " * "]
  • 輸出: 9
  • 解釋: 該算式轉化為常見的中綴算術表達式為:((2 + 1) * 3) = 9

思路: 棧, 每遇到一個操作符, 就對棧中的兩個數組進行計算, 注意: 棧中的順序與原來后綴表達式計算順序相反, 因此彈出來的兩個數字運算時交換順序注意: 棧中的順序與原來后綴表達式計算順序相反, 因此彈出來的兩個數字運算時交換順序.

代碼:

class Solution {public int evalRPN(String[] tokens) {// 0. 剪枝if(tokens.length == 1) return Integer.valueOf(tokens[0]);// 1. 定義棧Stack<Integer> sk = new Stack<>();// 2. 逐個處理for(String s : tokens) {// 2.1 處理運算符if("+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s)) {// 注意: 棧中的順序與原來后綴表達式計算順序相反, 因此彈出來的兩個數字運算時交換順序int n = sk.pop();int m = sk.pop();if("+".equals(s)) {sk.push(m + n);}else if("-".equals(s)) {sk.push(m - n);}else if("*".equals(s)) {sk.push(m * n);}else if("/".equals(s)) {sk.push(m / n);}}else {// 2.2 處理數字sk.push(Integer.valueOf(s));}}// 3. 返回return sk.pop();}
}

239. 滑動窗口最大值

239. 滑動窗口最大值

給定一個數組 nums,有一個大小為 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。

返回滑動窗口中的最大值。

進階:

你能在線性時間復雜度內解決此題嗎?

提示:

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

思路: 單調隊列, 保證隊頭為窗口內最大值, 保證每次隊列內有不多于k個元素

代碼:

class Solution {public int[] maxSlidingWindow(int[] nums, int k) {// 1. 定義容器ArrayDeque<Integer> q = new ArrayDeque<>();int n = nums.length,index = 0;int[] ans = new int[n - k + 1];// 2. 循環遍歷for(int i = 0;i < n;i++) {// 2.1 出: 將不符合窗口范圍的移出while(!q.isEmpty() && q.peek() < (i - k + 1)) q.poll();// 2.2 入: 先將比該數值小的從后往前依次移出(保證單調), 再放入while(!q.isEmpty() && nums[q.peekLast()] < nums[i]) q.pollLast();q.offer(i);// 2.3 收集: 當窗口中走夠k個元素時, 開始收集if(i >= k - 1) ans[index++] = nums[q.peek()];}// 3. 返回return ans;}
}

347.前 K 個高頻元素

347. 前 K 個高頻元素

給定一個非空的整數數組,返回其中出現頻率前 k 高的元素。

示例 1:

  • 輸入: nums = [1,1,1,2,2,3], k = 2
  • 輸出: [1,2]

示例 2:

  • 輸入: nums = [1], k = 1
  • 輸出: [1]

思路: map統計num及其出現次數, PriorityQueue用作小頂堆, 維護前k個出現次數最多的entry

代碼:

class Solution {public int[] topKFrequent(int[] nums, int k) {// 1. 定義容器int[] ans = new int[k];Map<Integer,Integer> map = new HashMap<>();PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2) -> o1[1] - o2[1]);// 2. 填充mapfor(int num : nums) {map.put(num,map.getOrDefault(num,0) + 1);}// 3. 填充pqSet<Map.Entry<Integer,Integer>> entries = map.entrySet();for(Map.Entry<Integer,Integer> e : entries) {int[] t = new int[2];t[0] = e.getKey();t[1] = e.getValue();pq.offer(t);// 維持小頂堆中3個出現次數最多元素if(pq.size() > k) pq.poll();}// 4. 返回for(int i = 0;i < k;i++) {ans[i] = pq.poll()[0];}return ans;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67473.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67473.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67473.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AJAX綜合案例——圖書管理

黑馬程序員視頻地址&#xff1a; AJAX-Day02-10.案例_圖書管理AJAX-Day02-10.案例_圖書管理_總結_V1.0是黑馬程序員前端AJAX入門到實戰全套教程&#xff0c;包含學前端框架必會的&#xff08;ajaxnode.jswebpackgit&#xff09;&#xff0c;一套全覆蓋的第25集視頻&#xff0c…

【編譯原理實驗二】——自動機實驗:NFA轉DFA并最小化

本篇適用于ZZU的編譯原理課程實驗二——自動機實驗&#xff1a;NFA轉DFA并最小化&#xff0c;包含了實驗代碼和實驗報告的內容&#xff0c;讀者可根據需要參考完成自己的程序設計。 如果是ZZU的學弟學妹看到這篇&#xff0c;那么恭喜你&#xff0c;你來對地方啦&#xff01; 如…

【redis進階】分布式鎖

目錄 一、什么是分布式鎖 二、分布式鎖的基礎實現 三、引入過期時間 四、引入校驗 id 五、引入lua 六、引入 watch dog (看門狗) 七、引入 Redlock 算法 八、其他功能 redis學習&#x1f973; 一、什么是分布式鎖 在一個分布式的系統中&#xff0c;也會涉及到多個節點訪問同一…

wordpress每隔24小時 隨機推薦一個指定分類下的置頂內容。

在WordPress中實現每隔24小時隨機推薦一個指定分類下的置頂內容&#xff0c;可以通過以下步驟實現&#xff1a; 1. 創建自定義函數 在主題的functions.php文件中添加以下代碼&#xff0c;用于創建一個定時任務&#xff0c;每隔24小時隨機選擇一個置頂文章并存儲到選項中&…

Blazor-@bind

數據綁定 帶有 value屬性的標記都可以使用bind 綁定&#xff0c;<div>、<span>等非輸入標記&#xff0c;無法使用bind 指令的&#xff0c;默認綁定了 onchange 事件&#xff0c;onchange 事件是指在輸入框中輸入內容之后&#xff0c;當失去焦點時執行。 page &qu…

RK3568 opencv播放視頻

文章目錄 一、opencv相關視頻播放類1. cv::VideoCapture 類主要構造方法&#xff1a;主要方法&#xff1a; 2. 視頻播放基本流程代碼示例&#xff1a; 3. 獲取和設置視頻屬性4. 結合 FFmpeg 使用5. OpenCV 視頻播放的局限性6. 結合 Qt 實現更高級的視頻播放總結 二、QT中的代碼…

pytorch邏輯回歸實現垃圾郵件檢測

完整代碼&#xff1a; import torch import torch.nn as nn import torch.optim as optim from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import numpy as…

【 CVE-2025-21298】 通過ghidriff查看完整補丁差異

ole32_dec24.dll-ole32.dll 差異 目錄 視覺圖表差異元數據 Ghidra 差異引擎 命令行二進制元數據差異程序選項

洛谷P3383 【模板】線性篩素數

題目鏈接&#xff1a;P3383 【模板】線性篩素數 - 洛谷 | 計算機科學教育新生態 題目難度&#xff1a;普及一 題目分析&#xff1a;本題是模板題&#xff0c;用到了線性篩法&#xff0c;其中原理是保證范圍內的每個合數都被刪掉&#xff08;在 bool 數組里面標記為非素數…

STM32標準庫移植RT-Thread nano

STM32標準庫移植RT-Thread Nano 嗶哩嗶哩教程鏈接&#xff1a;STM32F1標準庫移植RT_Thread Nano 移植前的準備 stm32標準庫的裸機代碼&#xff08;最好帶有點燈和串口&#xff09;RT-Thread Nano Pack自己的開發板 移植前的說明 本人是在讀學生&#xff0c;正在學習階段&a…

JVM--類加載器

概念 類加載器&#xff1a;只參與加載過程中的字節碼獲取并加載到內存中的部分&#xff1b;java虛擬機提供給應用程序去實現獲取類和接口字節碼數據的一種技術&#xff0c;也就是說java虛擬機是允許程序員寫代碼去獲取字節碼信息 類加載是加載的第一步&#xff0c;主要有以下三…

ECMAScript 6語法

1.ES6簡介 ECMAScript 6&#xff08;簡稱ES6&#xff09;是于2015年6月正式發布的JavaScript語言的標準&#xff0c;正式名為ECMAScript 2015&#xff08;ES2015&#xff09;。它的目標是使得JavaScript語言可以用來編寫復雜的大型應用程序&#xff0c;成為企業級開發語言 。 …

聯想Y7000+RTX4060+i7+Ubuntu22.04運行DeepSeek開源多模態大模型Janus-Pro-1B+本地部署

直接上手搓了&#xff1a; conda create -n myenv python3.10 -ygit clone https://github.com/deepseek-ai/Janus.gitcd Januspip install -e .pip install webencodings beautifulsoup4 tinycss2pip install -e .[gradio]pip install pexpect>4.3python demo/app_januspr…

Tez 0.10.1安裝

個人博客地址&#xff1a;Tez 0.10.1安裝 | 一張假鈔的真實世界 具體安裝步驟參照官網安裝手冊即可。此處只對官網手冊進行補充。 從官網下載apache-tez-0.10.1-bin.tar.gz進行安裝未成功&#xff0c;出現下面的異常。最終按照官網源代碼編譯的方式安裝測試成功。 環境 Had…

FastAPI + GraphQL + SQLAlchemy 實現博客系統

本文將詳細介紹如何使用 FastAPI、GraphQL&#xff08;Strawberry&#xff09;和 SQLAlchemy 實現一個帶有認證功能的博客系統。 技術棧 FastAPI&#xff1a;高性能的 Python Web 框架Strawberry&#xff1a;Python GraphQL 庫SQLAlchemy&#xff1a;Python ORM 框架JWT&…

微服務入門(go)

微服務入門&#xff08;go&#xff09; 和單體服務對比&#xff1a;里面的服務僅僅用于某個特定的業務 一、領域驅動設計&#xff08;DDD&#xff09; 基本概念 領域和子域 領域&#xff1a;有范圍的界限&#xff08;邊界&#xff09; 子域&#xff1a;劃分的小范圍 核心域…

深入解析 Linux 內核內存管理核心:mm/memory.c

在 Linux 內核的眾多組件中,內存管理模塊是系統性能和穩定性的關鍵。mm/memory.c 文件作為內存管理的核心實現,承載著頁面故障處理、頁面表管理、內存區域映射與取消映射等重要功能。本文將深入探討 mm/memory.c 的設計思想、關鍵機制以及其在內核中的作用,幫助讀者更好地理…

安卓通過網絡獲取位置的方法

一 方法介紹 1. 基本權限設置 首先需要在 AndroidManifest.xml 中添加必要權限&#xff1a; xml <uses-permission android:name"android.permission.INTERNET" /> <uses-permission android:name"android.permission.ACCESS_NETWORK_STATE" /&g…

【B站保姆級視頻教程:Jetson配置YOLOv11環境(二)SSH連接的三種方式】

B站同步視頻教程&#xff1a;https://www.bilibili.com/video/BV1m5wUeyEQD/ 在Jetson設備上配置YOLOv11環境時&#xff0c;SSH連接是實現遠程高效開發與管理的關鍵一環。不同的網絡環境和硬件配置可能會影響SSH連接的方式&#xff0c;本文將結合相關視頻內容&#xff0c;詳細…

視頻拼接,拼接時長版本

目錄 視頻較長&#xff0c;分辨率較大&#xff0c;這個效果很好&#xff0c;不耗用內存 ffmpeg imageio&#xff0c;適合視頻較短 視頻較長&#xff0c;分辨率較大&#xff0c;這個效果很好&#xff0c;不耗用內存 ffmpeg import subprocess import glob import os from nats…