【數據結構】面試OJ題———棧|隊列|互相實現|循環隊列|括號匹配

目錄

1. 有效的括號

思路:

2.用隊列實現棧?

思路:

3.用棧實現隊列

思路:

?4.設計循環隊列

思路:


1. 有效的括號

20. 有效的括號 - 力扣(LeetCode)

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

有效字符串需滿足:

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

思路:

左右括號匹配,有兩個需要考慮的點;

1.括號順序問題;

2.括號數量問題;

1.括號順序問題:括號都有對應的左右邊,出現這樣的 ({)} 就是錯誤的;只有相應的左括號會有對應的右括號在旁邊;

棧:先進后出;一組括號,先比較的是最后輸入的左括號;所以棧滿足此功能;

隊列:先進先出;最先輸入的左括號應該是與最后輸入的右括號比較,所以隊列不滿足此功能;

2.括號順序問題: 即使右括號都滿足了左括號,會有殘留問題,比如右括號多些,而此時空間已經為空;

我們構建一個棧的基本功能?;【數據結構】——棧|隊列(基本功能)-CSDN博客

// 支持動態增長的棧
typedef char STDataType;
typedef struct Stack
{STDataType* arr;	int top;		// 棧頂int capacity;  // 容量 
}Stack;// 初始化棧 
void StackInit(Stack* ps)
{assert(ps);assert(ps);ps->arr = NULL;ps->capacity = 0;ps->top = -1;	//表示棧頂元素
}// 入棧 
void StackPush(Stack* ps, STDataType data)
{//檢查容量if (ps->top + 1 == ps->capacity)	//top表示的是棧頂元素,先++top,再插入的,所以檢查+1位置是否可用{int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* newnode = (STDataType*)realloc(ps->arr,sizeof(STDataType) * newcapacity);assert(newnode);	//七匹狼式檢查是否開辟成功ps->arr = newnode;ps->capacity = newcapacity;}ps->top++;ps->arr[ps->top] = data;
}// 出棧 
void StackPop(Stack* ps)
{assert(ps);assert(ps->top >= 0);ps->top--;
}// 獲取棧頂元素 
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top >= 0);return ps->arr[ps->top];
}// 檢測棧是否為空,如果為空返回非零結果,如果不為空返回0 
bool StackEmpty(Stack* ps)
{assert(ps);if (ps->top < 0)	//為空{return true;}else{return false;}
}// 銷毀棧 
void StackDestroy(Stack* ps)
{assert(ps);ps->capacity = 0;ps->top = -1;free(ps->arr);ps->arr = NULL;
}

當括號字符串 所有左括號都存儲進棧中,當遇到右括號就開始逐個和棧頂括號比較;

?這里在于比較時,因為比較后還需要繼續比較,所以采取找到不符合的條件跳出循環;

在字符串循環結束后,要檢查是否棧為空

bool isValid(char* s) {Stack ps;StackInit(&ps);while(*s){//左括號入棧if(*s == '(' || *s == '{' || *s == '['){StackPush(&ps,*s);}//右括號與棧頂比較else{//檢查是否數量匹配,檢查棧是否還有元素,為空返回非0if(StackEmpty(&ps)){StackDestroy(&ps);return false;}//左右括號比較,不相等返回faslechar tmp = StackTop(&ps);StackPop(&ps); //移除棧頂元素if((tmp != '(' && *s == ')')||( tmp != '{' && *s == '}')|| (tmp != '[' && *s == ']')){StackDestroy(&ps);return false;}}++s;}bool tmp = StackEmpty(&ps);StackDestroy(&ps);return tmp;
}

2.用隊列實現棧?

225. 用隊列實現棧 - 力扣(LeetCode)

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

實現?MyStack?類:

  • void push(int x)?將元素 x 壓入棧頂。
  • int pop()?移除并返回棧頂元素。
  • int top()?返回棧頂元素。
  • boolean empty()?如果棧是空的,返回?true?;否則,返回?false?。

思路:

?棧是先進后出的結構,而隊列是先進先出的;

兩個隊列,數據存儲到隊列1中后,按照先進先出的結構,將size(元數個數)-1移動到隊列2中,再輸出隊列1的話,就實現了棧的結構,先進后出;

可以總結為:如果要輸入元素,就輸入到空隊列中

//將元素X壓入棧頂
void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&obj->q1))   //為空返回非0,取反{QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}
}

如何找到棧頂元素呢,我們可以將不為空的隊列中 size(有效元素個數)-1個 數據移動到空隊列中,再輸出原不為空的隊列;

我們采取假設法,找到不為空的隊列,假設某一隊列為empty,另外一個隊列為noempty;然后if條件判斷假設;?

//移除并返回棧頂元素
int myStackPop(MyStack* obj) {//將size-1個元素移動到 另一個空隊列中//假設q1隊列為空,q2不為空Queue* empty = &obj->q1;Queue* noempty = &obj->q2;//驗證假設if(!QueueEmpty(&obj->q1)){empty = &obj->q2;noempty = &obj->q1;}//將size-1個元素 移動到空隊列中while(QueueSize(noempty)>1){QueuePush(empty,QueueFront(noempty));QueuePop(noempty);}int top = QueueFront(noempty);    //此刻該隊列僅有需要的數據QueuePop(noempty);return top;}

?這兩個是這道題較為麻煩的函數,另外的函數需求因為較為簡單,我就直接碼上講解;

且這段代碼是這道題一半的代碼,另外一般就是隊列的基本功能實現代碼,可以去【數據結構】——棧|隊列(基本功能)-CSDN博客獲取完整的代碼,復制過來即可;

注:這里釋放內存是由里往外,因為結構定義了多重?

?

MyStack* myStackCreate() {MyStack* pst =  (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}//將元素X壓入棧頂
void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&obj->q1))   //為空返回非0,取反{QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}
}
//移除并返回棧頂元素
int myStackPop(MyStack* obj) {//將size-1個元素移動到 另一個空隊列中//假設q1隊列為空,q2不為空Queue* empty = &obj->q1;Queue* noempty = &obj->q2;//驗證假設if(!QueueEmpty(&obj->q1)){empty = &obj->q2;noempty = &obj->q1;}while(QueueSize(noempty)>1){QueuePush(empty,QueueFront(noempty));QueuePop(noempty);}int top = QueueFront(noempty);QueuePop(noempty);return top;}
//返回棧頂元素
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1))   //為空返回非0,取反{return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}//如果棧是空,返回true,非空 返回fasle
bool myStackEmpty(MyStack* obj) {if(QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2))    //表示為空{return true;}elsereturn false;
}void myStackFree(MyStack* obj) {    //注意釋放順序QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);
}

3.用棧實現隊列

232. 用棧實現隊列 - 力扣(LeetCode)

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

實現?MyQueue?類:

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

思路:

?這道題和題2相似,要實現1先出去,就是先把入棧的元素全部移動到出棧中,就實現了隊列的結構;

與之不同的是:這邊需要把全部的數據移動到另一個棧;

可以定義兩個棧為:

pushst棧:用來數據存放的棧;

popst棧: 用來輸出數據的棧;

1.需要獲得棧內數據時,先檢查popst棧是否為空,如果不為空,返回該棧數據即刻;

2.如果為空,先將pushst棧數據導入到popst棧內,在進行返回popst棧數據?

int myQueuePeek(MyQueue* obj) {if(!STEmpty(&obj->popst))   //popst棧有數據  直接返回棧頂元素{return STTop(&obj->popst);}else{//先將數據導入到popst棧while(!STEmpty(&obj->pushst)){STPush(&obj->popst,STTop(&obj->pushst));STPop(&obj->pushst);}//返回棧頂元素return STTop(&obj->popst);}
}

?注:這里和題2一樣,注意釋放順序

因為其他功能較為思路明了,解析過程會在代碼中解釋;?

棧函數接口實現功能代碼在【數據結構】——棧|隊列(基本功能)-CSDN博客

MyQueue* myQueueCreate() {MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->pushst);STInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x) {//數據進到pushst棧,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))   //popst棧有數據  直接返回棧頂元素{return STTop(&obj->popst);}else{//先將數據導入到popst棧while(!STEmpty(&obj->pushst)){STPush(&obj->popst,STTop(&obj->pushst));STPop(&obj->pushst);}//返回棧頂元素return STTop(&obj->popst);}
}bool myQueueEmpty(MyQueue* obj) {if(STEmpty(&obj->pushst) && STEmpty(&obj->popst)){return true;}elsereturn false;
}void myQueueFree(MyQueue* obj) {STDestrory(&obj->pushst);STDestrory(&obj->popst);free(obj);
}

?4.設計循環隊列

622. 設計循環隊列 - 力扣(LeetCode)

?設計你的循環隊列實現。 循環隊列是一種線性數據結構,其操作表現基于 FIFO(先進先出)原則并且隊尾被連接在隊首之后以形成一個循環。它也被稱為“環形緩沖器”。

思路:

?這里有兩種數據結構可以選擇:數組和鏈表;

鏈表對后續的操作比較方便,但是不好控制,而且構建的時候也極為麻煩;

如果用數組 需要考慮的是如何規避為滿和為空的判斷

?

采用數組的話,我們定義front,back;來進行判斷循環點;

?

這里的問題就是如何規避 為滿和為空的問題;?

解決:1.可以定義一個size;在front == back的基礎上,size == 0 就是空

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? size != 0就是滿;

? ? ? ? 2. 可以多開辟一塊空間;動態空間;

?

多開辟一塊空間,這塊空間是動態移動的,但是不存儲數據;

當front == back時,就是空;

當 back+1 == front 就是滿,

這里因為數組 如果在邊界點的話 會導致越界,

所以采取取模來規范范圍;也達到了循環的條件

?這里需要注意的就是獲取最后一個結點;

因為back是指向最后一個數據的下一個位置;如果back在邊界 -1 有可能越界;

需要特殊處理規范這塊;

?

取模的操作:如果該數大于本身,就不會有影響;?

這里刪除和增加一個數據,都有可能引起越界;所以在對back front操作后,都要規范范圍;

取模實際空間大小?

typedef struct {int* parr;  //動態開辟int front;  //頭結點int back;   //指向尾結點的下一個int size;      //實際開辟的空間
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->parr = (int*)malloc(sizeof(int)*(k+1));   //多開辟一塊空間obj->front = 0;obj->back = 0;obj->size= k+1;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front == obj->back;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->back+1) % obj->size == obj->front;  //滿了返回真
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//先判斷是否滿了if(myCircularQueueIsFull(obj))  //滿了返回真return false;obj->parr[obj->back] = value;obj->back++;obj->back %= obj->size;return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {//判斷是否為空if(myCircularQueueIsEmpty(obj))return false;obj->front++;obj->front %= obj->size;return true;
}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->parr[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->parr[(obj->back-1 + obj->size) % obj->size];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->parr);free(obj);
}

?

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

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

相關文章

Hive SQL間隔連續問題

問題引入 下面是某游戲公司記錄的用戶每日登錄數據, 計算每個用戶最大的連續登錄天數&#xff0c;定義連續登錄時可以間隔一天。舉例&#xff1a;如果一個用戶在 1,3,5,6,9 登錄了游戲&#xff0c;則視為連續 6 天登錄。 id dt1001 2021-12-121002 2021-12-12…

visual studio code 好用的插件

vscode-icons Better comments 該插件對不同類型的注釋會附加了不同的顏色&#xff0c;更加方便區分&#xff0c;幫助我們在代碼中創建更人性化的注釋。 Error Lens Error Lens插件是一款可以檢測你編寫的代碼的語法錯誤&#xff0c;并且會顯示出對語法錯誤的診斷信息…

USB的高速速率是如何確定的?

從全局說起。先說host對dev的插入檢測。由于dev插入到host&#xff0c;導致為0的D和D-線突然有了電平變化&#xff0c;有且只有一根線的電平會變。在高速和全速模式下&#xff0c;D線會被拉高&#xff1b;在低速模式下D-線會被拉高。同時&#xff0c;host會對插入的dev進行消抖…

RCNN 學習

RCNN算法流程 RCNN算法流程可分為4個步驟 一張圖像生成1K~2K個候選區域&#xff08;使用Selective Search方法&#xff09;對每個候選區域&#xff0c;使用深度網絡圖特征特征送入每一類的SVM分類器&#xff0c;判別是否屬于該類使用回歸期器細修正候選框位置 1.候選區域的生…

【星海隨筆】Prometheus(一)

注&#xff1a;Pagerduty作為報警系統&#xff0c;出鏡率很高。 雖然收費&#xff0c;但對于企業來說很便宜。 一個月幾十美金 不太支持中文&#xff0c;主要是語音方面。 Prometheus 查詢語句 &#xff0c; 基于數學運算模式的監控查詢 我們計算一下一天多少秒 1 * 24 * 60 *…

ChatGPT是科學還是藝術?

OpenAI最近談到GPT4變懶的問題&#xff0c;說“它更像是多人共同參與的藝術創作”&#xff0c;那到底大模型是科學還是藝術&#xff1f;

公式識別任務各個鏈條全部打通

目錄 引言公式識別任務是什么&#xff1f;公式識別任務解決方案初探使用建議寫在最后 引言 隨著LaTeX-OCR模型轉換問題的解決&#xff0c;公式識別任務中各個鏈條已經全部打通。小伙伴們可以放開膀子干了。 解決業界問題的方案&#xff0c;并不是單獨訓練一個模型就完事了&am…

如何確認網站是否有漏洞,如何找出網站存在的漏洞,找到漏洞該如何處理

如何確認網站或者服務器是否有漏洞 判斷一個網站是否是存在漏洞的方法&#xff1a; 1.可以借助德迅云安全漏洞掃描功能來檢查漏洞。 2.打開德迅云安全首頁&#xff0c;點擊最上面導航欄中的“安全產品”。 3.滑到“漏洞掃描”&#xff0c;選擇“產品價格”服務。 4.選擇您需…

【力扣】141和142環形鏈表

141.環形鏈表 法一&#xff1a;快慢指針 思路&#xff1a; 用兩個指針slow,fast,后者能比前者多走一步路&#xff0c;那判斷是不是有環&#xff0c;只需要判斷是否會相遇。 就是有一個能比烏龜跑2倍快的兔子&#xff0c;兩小只都在有環的路上跑&#xff0c;那是不是肯定會相…

golang開發之個微機器人的二次開發

簡要描述&#xff1a; 下載消息中的文件 請求URL&#xff1a; http://域名地址/getMsgFile 請求方式&#xff1a; POST 請求頭Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 參數&#xff1a; 參數名必選類型…

java基礎之TreeMap詳解

TreeMap詳解 TreeMap是Map接口的一個實現類&#xff0c;底層基于紅黑樹的實現&#xff0c;按照key的順序存儲 TreeMap 從繼承結構可以看到TreeMap除了繼承了AbstractMap類&#xff0c;還實現了NavigableMap接口&#xff0c;而NavigableMap接口是繼承自SortedMap接口的&#xff…

使用Vue3+Typescript手寫一個日歷簽到組件

設計理念 昨天寫了個簡單美觀的日歷簽到組件&#xff0c;使用的是Vue3TypeScript&#xff0c;大概邏輯是先找到本月份第一天是周幾&#xff0c;然后開始填充月份日期&#xff1a;weeksArray:[[]]:之后渲染到表格中&#xff0c;對于簽到事件觸發則先判斷是否是今天且還未沒有簽…

【PyTorch】模型訓練過程優化分析

文章目錄 1. 模型訓練過程劃分1.1. 定義過程1.1.1. 全局參數設置1.1.2. 模型定義 1.2. 數據集加載過程1.2.1. Dataset類&#xff1a;創建數據集1.2.2. Dataloader類&#xff1a;加載數據集 1.3. 訓練循環 2. 模型訓練過程優化的總體思路2.1. 提升數據從硬盤轉移到CPU內存的效率…

SPRD Android 13 需要在設置--顯示--鎖定屏幕--雙行時鐘--<關閉>

開始去改默認值沒生效 --- a/frameworks/base/packages/SettingsProvider/res/values/defaults.xml +++ b/frameworks/base/packages/SettingsProvider/res/values/defaults.xml @@ -336,4 +336,6 @@<integer name="def_navigation_bar_config">0</integer…

西南科技大學數字電子技術實驗三(MSI邏輯器件設計組合邏輯電路及FPGA的實現)FPGA部分

一、實驗目的 進一步掌握MIS(中規模集成電路)設計方法。通過用MIS譯碼器、數據選擇器實現電路功能,熟悉它們的應用。進一步學習如何記錄實驗中遇到的問題及解決方法。二、實驗原理 1、4位奇偶校驗器 Y=S7i=0DiMi D0=D3=D5=D6=D D1=D2=D4=D7= `D 2、組合邏輯電路 F=A`B C …

面試計算機網絡八股文五問五答第二期

面試計算機網絡八股文五問五答第二期 作者&#xff1a;程序員小白條&#xff0c;個人博客 相信看了本文后&#xff0c;對你的面試是有一定幫助的&#xff01; ?點贊?收藏?不迷路&#xff01;? 1.OSI七層協議&#xff1f; 2. TCP和UDP傳輸協議的區別&#xff1f; TCP是可…

C語言_常見位操作

C語言_常見位操作 文章目錄 C語言_常見位操作一、位操作函數二、代碼示例 一、位操作函數 設置某位為1或者對某位清0、獲取某位的值、對某位取反 /*對某位置1*/ unsigned Setbit(unsigned x,int n) {return x | 1 << n; }/*對某位清0*/ unsigned Resetbit(unsigned x,…

為什么要用向量檢索

之前寫過一篇文章&#xff0c;是我個人到目前階段的認知&#xff0c;所做的判斷。我個人是做萬億級數據的搜索優化工作的。一直在關注任何和搜索相關的內容。 下一代搜索引擎會什么&#xff1f;-CSDN博客 這篇文章再來講講為什么要使用向量搜索。 在閱讀這篇文章之前呢&#xf…

【網絡安全】網絡設備可能面臨哪些攻擊?

網絡設備通常是網絡基礎設施的核心&#xff0c;并控制著整個網絡的通信和安全&#xff0c;同樣面臨著各種各樣的攻擊威脅。 對網絡設備的攻擊一旦成功&#xff0c;并進行暴力破壞&#xff0c;將會導致網絡服務不可用&#xff0c;且可以對網絡流量進行控制&#xff0c;利用被攻陷…

【JavaEE】線程池

作者主頁&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感謝你閱讀本文&#xff0c;歡迎一建三連哦。 本文于《JavaEE》專欄&#xff0c;本專欄是針對于大學生&#xff0c;編程小白精心打造的。筆者用重金(時間和精力)打造&…