數據結構 棧和隊列 力扣例題AC——代碼以及思路記錄

20. 有效的括號

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

有效字符串需滿足:

  1. 左括號必須用相同類型的右括號閉合。
  2. 左括號必須以正確的順序閉合。
  3. 每個右括號都有一個對應的相同類型的左括號。

AC

typedef char STDataType;
typedef struct Stack
{STDataType* a;int top; //標識棧頂位置,元素數量int capacity; //棧的容量
}ST;void STInit(ST* pst);
void STDestory(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;// 1.表示top指向棧頂元素的下一個位置pst->top = 0;// 2.表示top指向棧頂元素//pst->top = -1; // top為0的話不清楚是top為0還是空,因此空的時候給-1//位置(下標)   top     0     1//數值        -1(空)   0     1//top = 1指向棧頂元素的下一個位置}void STDestory(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;}void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; //如果棧的當前容量為0,將其設為4,否則將其擴大為當前容量的兩倍STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp; //將原來棧中數據的指針更新為新的內存空間的指針pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}int STSize(ST* pst)
{assert(pst);return pst->top;}bool isValid(char* s) {ST st;STInit(&st);while(*s){if(*s == '(' || *s == '[' || *s == '{'){STPush(&st,*s);}else{// 這種情況是右括號多,現在有右括號,但是現在存左括號的棧里是空的if(STEmpty(&st)){STDestory(&st);return false;}// 棧里面取左括號進行判斷char top = STTop(&st);STPop(&st);if((*s == ')' && top != '(')|| (*s == ']' && top != '[')|| (*s == '}' && top != '{')){return false;}}++s;}// 若左右括號數量不相同,棧里可能還會有括號,上述只能解決可以對應的// 棧為空,返回真,說明數量也匹配,這行解決左括號多,右括號少的情況bool ret = STEmpty(&st);STDestory(&st);return ret;
}

代碼思路

這道題使用C解題,需要創建一個棧,但是使用C++可以直接用棧,暫時先使用C語言解題,因此上述代碼實現了棧的功能(手搓哈哈哈,后續會更新C++版本),具體解題函數為最后一個。在棧里存儲左括號,如果遍歷到了左括號就入棧,遍歷到了右括號,就拿出棧里最后一個入棧的,也就是離該右括號最近的左括號進行判斷是不是相匹配的,這一步判斷由于是字符,所以需要將情況都列出來,然后只要不匹配就返回false,若果匹配s就繼續下一個判斷,但是在該左括號判斷后一定要出棧。

但是有種情況是右括號比左括號多,遍歷到了右括號,此時存左括號的棧是空的,這時候直接返回false,所以這里需要檢測棧是否為空,返回前需要將棧清空,否則有可能發生內存泄漏。

還有一種情況是左括號比右括號多,在右括號都遍歷完以后,棧內依舊存著左括號,因此在可以匹配的括號都判斷以后,需要檢測棧內是否為空,然后將棧清空。最后返回值使用了棧是否為空的判斷返回值ret,因為如果ret為true,就說明棧確實是空的,匹配正好都對應,符合題目要求,而返回false說明棧不空,左括號還有多余的,不是匹配的。

另外在創建實例的時候,要注意不能使用和形參一樣的變量,這段代碼中使用的是st,因為函數傳參寫的是s,否則會分不清到底是存儲需要入棧的左括號還是指向字符數組的指針。

225. 用隊列實現棧

請你僅使用兩個隊列實現一個后入先出(LIFO)的棧,并支持普通棧的全部四種操作(push、top、pop 和 empty)。

AC

typedef int QDataType;
typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead; // 頭指針QNode* ptail; // 尾指針int size;
}Queue;void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;if (pq->ptail == NULL){pq->ptail = pq->phead = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}void QueuePop(Queue* pq)
{assert(pq);// 空節點assert(pq->phead);QNode* del = pq->phead;pq->phead = pq->phead->next;free(del);// 一個節點的時候,phead向前走// del被free,ptail此時和del指的是一個節點,如果free,就變成了野指針if (pq->phead == NULL){pq->ptail = NULL;}pq->size--;
}QDataType QueueFront(Queue* pq)
{assert(pq);// 空節點assert(pq->phead);return pq->phead->val;
}QDataType QueueBack(Queue* pq)
{assert(pq);// 空節點assert(pq->phead);return pq->ptail->val;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}//上述代碼為隊列的實現
//下邊開始用隊列實現棧的邏輯typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&obj->q1)){QueuePush(&obj->q1, x);}else{QueuePush(&obj->q2, x);}
}int myStackPop(MyStack* obj) {Queue* emptyq = &obj->q1;Queue* nonemptyq = &obj->q2;if(!QueueEmpty(&obj->q1)){emptyq = &obj->q2;nonemptyq = &obj->q1;}// 非空隊列前N-1個導入空隊列,最后一個就是棧頂元素while(QueueSize(nonemptyq) > 1){QueuePush(emptyq, QueueFront(nonemptyq));QueuePop(nonemptyq);}int top = QueueFront(nonemptyq);QueuePop(nonemptyq);return top;
}int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}void myStackFree(MyStack* obj) {QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}/*** Your MyStack struct will be instantiated and called as such:* MyStack* obj = myStackCreate();* myStackPush(obj, x);* int param_2 = myStackPop(obj);* int param_3 = myStackTop(obj);* bool param_4 = myStackEmpty(obj);* myStackFree(obj);
*/

代碼思路

棧和隊列的區別就是先進先出和后進先出,用隊列實現棧,假設現在隊列內已經入隊 1 2 3 4 5 ,要出隊的話必定是 1 2 3 4 5,現在是棧進行出棧,那么就是 5 4 3 2 1,此題給了我們兩個隊列,當我們要出棧,也就是讓 5 先出,就可以把隊列 1 中的 1 2 3 4 依次出隊,并同時入隊列 2,然后彈出 5,接著再將隊列 2 中的 1 2 3 出隊列并入隊列 1,彈出 4……依次這樣交替執行,就可以用兩個隊列實現棧了。(雖然這道題實際上并沒有什么卵用,但是邏輯結構真的很鍛煉人,我也是只清楚大致思路,代碼一團糟,可參考力扣官方給的解題代碼)

232. 用棧實現隊列

請你僅使用兩個棧實現先入先出隊列。隊列應當支持一般隊列支持的所有操作(push、pop、peek、empty):

實現 MyQueue 類:

  • void push(int x) 將元素 x 推到隊列的末尾
  • int pop() 從隊列的開頭移除并返回元素
  • int peek() 返回隊列開頭的元素
  • boolean empty() 如果隊列為空,返回 true ;否則,返回 false

AC

typedef int STDataType;
typedef struct Stack
{STDataType* a;int top; //標識棧頂位置,元素數量int capacity; //棧的容量
}ST;void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;pst->top = 0;
}void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; //如果棧的當前容量為0,將其設為4,否則將其擴大為當前容量的兩倍STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp; //將原來棧中數據的指針更新為新的內存空間的指針pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];}bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}int STSize(ST* pst)
{assert(pst);return pst->top;
}//上述代碼為棧的實現
//下邊開始用棧實現隊列的邏輯typedef struct {ST pushst;ST popst;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->pushst);STInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x) {STPush(&obj->pushst, x);
}int myQueuePop(MyQueue* obj) {int front = myQueuePeek(obj);STPop(&obj->popst);return front;
}int myQueuePeek(MyQueue* obj) {if(STEmpty(&obj->popst)){// 倒數據過來while(!STEmpty(&obj->pushst)){STPush(&obj->popst, STTop(&obj->pushst));STPop(&obj->pushst);}}return STTop(&obj->popst);
}bool myQueueEmpty(MyQueue* obj) {return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}void myQueueFree(MyQueue* obj) {STDestroy(&obj->pushst);STDestroy(&obj->popst);free(obj);
}

代碼思路

用棧實現隊列,假設現在棧內已經入隊 1 2 3 4 5 ,要出棧的話必定是 5 4 3 2 1,現在是隊列進行出隊列,那么就是 1 2 3 4 5 ,此題給了我們兩個棧,當我們要出隊列,也就是讓 1 先出,就可以把棧 1 中的 5 4 3 2 依次出棧,并同時入棧 2,然后彈出 1,接著棧 2 中的 5 4 3 2 出棧就已經是隊列需要的順序了,執行棧2的出棧就是整個隊列的出隊機制了。Peek是查隊列頭部元素,那就是棧2的頂部元素,棧1如果為空直接返回棧2的頂部元素,不為空先pop到棧2再返回。說實話棧實現隊列更容易一些,到這里邏輯比隊列實現棧清楚許多了

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

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

相關文章

mysql使用連接池

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言一、mysql連接池?二、使用步驟1.引入庫 前言 提示:這里可以添加本文要記錄的大概內容: 例如: 提示&#xff1a…

深入理解Flutter中的StreamSubscription和StreamController

在Flutter中,StreamSubscription和StreamController是處理異步數據流的重要工具。它們提供了一種方便的方式來處理來自異步事件源的數據。本文將深入探討它們的區別以及在實際應用中的使用場景。 StreamSubscription StreamSubscription代表了對數據流的訂閱&…

代碼隨想錄算法訓練營番外 刷題日記0301 || 29、兩數相除,31、下一個排列

29、兩數相除 思路:不斷相減就是求解的最直接方法,我這樣計算時間復雜度有點高 // 時間復雜度O(count*divisor) // 空間復雜度O(1)class Solution {int res 0;public int divide(int dividend, int divisor) {// dividend 是被除數if(dividend 0) …

技術棧選型的時候,ruby、go、java、vue、react應該怎么選擇?

選擇適合項目需求、團隊技術背景和偏好、開發速度、性能要求以及可擴展性的技術棧和框架是一個綜合考慮的過程,沒有一種通用的最佳選擇,取決于具體情況。 選擇Vue.js或React應該綜合考慮項目的需求、團隊的技術背景和偏好、生態系統的支持和發展趨勢等因…

隨記-點選驗證碼

文字驗證碼(點擊文字) 模板匹配(從一張圖片中尋找 icon),放棄,目前準確率不高,且處理過程復雜 灰度處理將 complete_image_path 截取并另存為 target_image_path, verify_image_path…

WPF真入門教程30--順風物流單據管理系統

1、教程回顧 到現在為止,真入門系列教程已完成了29刺由淺入深地講解,當然不可能講到了WPF的所有技能點,但讀者看到了wpf的內部各種功能及之間的聯系,在此基礎上,提供一個完整有效的綜合項目,本項目采用的是…

c++知識點之 --this

在成員函數中存在。struct和class每個成員函數都隱含一個名為this的指針形參,并且它是該成員函數的第一個參數,當某個對象調用成員函數時,就會把該對象的地址傳給被調用成員函數的隱式形參this。 this是一個指針 ,存放的是當前對象…

加密與安全_深入了解Hmac算法(消息認證碼)

文章目錄 PreHMAC概述常見的Hmac算法Code隨機的key的生成 KeyGeneratorHmacMD5用Hmac算法取代原有的自定義的加鹽算法 HmacMD5 VS MD5HmacSHA256 Pre 加密與安全_深入了解哈希算法中我們提到, 存儲用戶的哈希口令時,要加鹽存儲,目的就在于抵…

操作系統系列學習——CPU管理的直觀想法

文章目錄 前言CPU管理的直觀想法 前言 一個本碩雙非的小菜雞,備戰24年秋招,計劃學習操作系統并完成6.0S81,加油! 本文總結自B站【哈工大】操作系統 李治軍(全32講) 老師課程講的非常好,感謝 【…

OpenLayers線性漸變和中心漸變(徑向漸變)

目錄 1.前言2.添加一個面要素3.線性漸變3.1 第一個注意點3.2 第二個注意點 4.中心漸變(徑向漸變)5.總結 1.前言 OpenLayers官網有整個圖層的漸變示例,但是沒有單個要素的漸變示例,我們這里來補充一下。OpenLayers中的漸變是通過fi…

python defaultdict

python中的dict是一個重要的數據類型,知道如何使用這個數據類型很簡單,但是這個類型使用過程中容易進入一些誤區,這篇文章主要對defaultdict方法的講解,深入的了解dict數據類型。 字典(dictionary)數據類型…

編譯鏈接實戰(22)C/C++代碼覆蓋率統計報告生成

文章目錄 GCOV 工具簡介gcov 使用lcov相關編譯選項 GCOV 工具簡介 gcov是一個測試代碼覆蓋率的工具,它是 gcc 自帶的查看代碼覆蓋率的工具。 與GCC結合使用,可以分析您的程序以幫助創建更高效、運行更快的代碼,并發現程序中未經測試的部分。…

PCIE 4.0 L0s/L1/L2

L0是PCIE設備正常工作的狀態,當設備鏈路處于非工作狀態可以跳轉大相應的低功耗狀態,L0s是一種可以快速恢復到L0的低功耗狀態;L1必須經過Reovery狀態才可以恢復到L0狀態;L2需要從Detect開始逐步進入到L0狀態。它們的恢復時間依次延…

麒麟銀河操作系統V10部署ffmpeg(也能用于Linux系統)

麒麟銀河操作系統V10部署ffmpeg(也能用于Linux系統) 部署ffmpeg用來處理視頻的各種操作 想使用ffmpeg,要先安裝nasm,yasm,x264之后,否則會報錯 nkvers 查看麒麟操作系統版本 cat /proc/version #查看linux版本信息 uname -a …

Android修行手冊-Chaquopy中opencv、numpy的初步應用

Unity3D特效百例案例項目實戰源碼Android-Unity實戰問題匯總游戲腳本-輔助自動化Android控件全解手冊再戰Android系列Scratch編程案例軟考全系列Unity3D學習專欄藍橋系列ChatGPT和AIGC 👉關于作者 專注于Android/Unity和各種游戲開發技巧,以及各種資源分…

SpringBoot源碼解讀與原理分析(三十八)SpringBoot整合WebFlux(一)WebFlux的自動裝配

文章目錄 前言第13章 SpringBoot整合WebFlux13.1 響應式編程與Reactor13.1.1 命令式與響應式13.1.2 異步非阻塞13.1.3 觀察者模式13.1.4 響應性13.1.5 響應式流13.1.6 背壓13.1.7 Reactor13.1.7.1 Publisher13.1.7.2 Subscriber13.1.7.3 Subscription13.1.7.4 Processor13.1.7.…

BF算法實現(Python,C++)

BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是將目標串S的第一個字符與模式串T的第一個字符進行匹配,若相等,則繼續比較S的第二個字符和 T的第二個字符;若不相等,則比…

Leetcoder Day32| 貪心算法part05

763.劃分字母區間 字符串 S 由小寫字母組成。我們要把這個字符串劃分為盡可能多的片段,同一字母最多出現在一個片段中。返回一個表示每個字符串片段的長度的列表。 示例: 輸入:S "ababcbacadefegdehijhklij"輸出:[9,7…

今日早報 每日精選15條新聞簡報 每天一分鐘 知曉天下事 3月2日,星期六

每天一分鐘,知曉天下事! 2024年3月2日 星期六 農歷正月廿二 1、 氣象局:3月份仍有5次冷空氣影響我國;全國多地或提前入春。 2、 央行:將外籍來華人員移動支付單筆交易限額由1000美元提高到5000美元。 3、 神舟十七號航…

全量知識系統問題及SmartChat給出的答復 之8 三套工具之3語法解析器 之1

Q19. 問題 : 解釋單詞解釋單詞occupied 的字典條目 (word-def occupiedinterest 5type EBsubclass SEBtemplate (script $Demonstrateactor nilobject nildemands nilmethod (scene $Occupyactor nillocation nil))fill (((actor) (top-of *actor-s…