leetcode每日一練:鏈表OJ題

鏈表經典算法OJ題

1.1 移除鏈表元素

題目要求:

給你一個鏈表的頭節點?head?和一個整數?val?,請你刪除鏈表中所有滿足?Node.val == val?的節點,并返回?新的頭節點?。

示例 1:

輸入:head = [1,2,6,3,4,5,6], val = 6
輸出:[1,2,3,4,5]

示例 2:

輸入:head = [], val = 1
輸出:[]

示例 3:

輸入:head = [7,7,7,7], val = 7
輸出:[]

解題思路:

思路1:

定義兩個指針,一個指向當前節點,一個指向當前節點的下一個節點,如果下一個節點是要刪除的節點就將當前節點的next存儲下一個節點的再下一個節點的地址,然后free那個節點。知道遍歷完原鏈表,該思路是改變原鏈表。

思路2:

建立一個新的鏈表,遍歷原鏈表,將原鏈表中的非刪除節點給新的鏈表,遍歷結束后新鏈表中沒有要刪除節點。

struct ListNode{int val;struct ListNode *next;
};
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* Newhead, * NewTail;//一個頭鏈表,一個鏈表尾部Newhead = NewTail = NULL;//遍歷原鏈表struct ListNode* pcur = head;while (pcur){if (pcur->val != val){if (Newhead == NULL){Newhead = NewTail = pcur;}else{NewTail->next = pcur;NewTail = NewTail->next;}}pcur = pcur->next;}//如果要刪除值在原鏈表為節點,新鏈表的尾節點就不會指向NULL,所以這里要判斷if (NewTail){NewTail->next = NULL;}return Newhead;
}

1.2 反轉鏈表

題目要求:

給你單鏈表的頭節點?head?,請你反轉鏈表,并返回反轉后的鏈表。

示例 1:

輸入:head = [1,2,3,4,5]
輸出:[5,4,3,2,1]

示例 2:

輸入:head = [1,2]
輸出:[2,1]

示例 3:

輸入:head = []
輸出:[]

進階:鏈表可以選用迭代或遞歸方式完成反轉。你能否用兩種方法解決這道題?

解題思路:

可以定義三個新的節點類型的指針變量n1、n2、n3。然后就可以使用這三個指針來反轉鏈表。首先n1初始化為NULL,n2初始化為head鏈表頭結點,n3則是head頭結點的下一個節點。然后循環n2->next = n1,?n1 = n2,?n2 = n3,n3 = n3->next。循環往復就完成了反轉鏈表的操作。

typedef struct ListNode{int val;struct ListNode *next;
}*pList;//反轉鏈表函數實現
pList reverselist(pList head){if (head == NULL){return NULL;}pList n1, n2, n3;n1 = NULL, n2 = head, n3 = head->next;while (n2){n2->next = n1;n1 = n2;n2 = n3;if(n3)//如果n3為NULL就不再向后訪問了n3 = n3->next;}return n1;
}//以下調用上面函數的main是我自己寫的,可以供大家參考
int main()
{//創建鏈表struct ListNode* phead, *pTail, *p;phead = pTail = NULL;int n = 0;printf("請輸入要創建鏈表節點個數:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p = (pList)malloc(sizeof(struct ListNode));printf("請輸入第%d個節點的值:>", i + 1);scanf("%d", &(p->val));p->next = NULL;if (phead == NULL){phead = p;pTail = phead;}else{pTail->next = p;pTail = pTail->next;}}//調用反轉鏈表函數pList Newhead = reverselist(phead);if (Newhead == NULL){perror("reverselist");return;}phead = Newhead;//打印鏈表節點數據while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;//銷毀鏈表while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已釋放第%d條節點\n", i);i++;}return 0;
}

1.3 合并兩個有序鏈表

題目要求:

將兩個升序鏈表合并為一個新的?升序?鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。?

示例 1:

輸入:l1 = [1,2,4], l2 = [1,3,4]
輸出:[1,1,2,3,4,4]

示例 2:

輸入:l1 = [], l2 = []
輸出:[]

示例 3:

輸入:l1 = [], l2 = [0]
輸出:[0]

解題思路:

定義兩個新的節點指針,一個頭節點,一個尾結點。比較兩個原鏈表當前節點的數據大小,然后插入新的鏈表,知道插完為止

typedef struct ListNode {int val;struct ListNode* next;
}*pList;
//合并兩個有序鏈表函數實現
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if (list1 == NULL){return list2;}if (list2 == NULL){return list1;}struct ListNode* cur1, *cur2;cur1 = list1, cur2 = list2;struct ListNode* phead, * pTail;phead = pTail = (struct ListNode*)malloc(sizeof(struct ListNode));while (cur1 && cur2) {if (cur1->val < cur2->val){pTail->next = cur1;pTail = pTail->next;cur1 = cur1->next;}else{pTail->next = cur2;pTail = pTail->next;cur2 = cur2->next;}}if (cur1) {pTail->next = cur1;}if (cur2) {pTail->next = cur2;}struct ListNode* retList = phead->next;free(phead);return retList;
}
//以下創建鏈表調用函數的代碼是自己寫的,只為調用上面函數,不是鏈表規范創建。僅供參考
int main()
{struct ListNode* phead1, pTail1, p1;struct ListNode* phead2, pTail2, p2;phead1 = pTail1 = NULL;phead2 = pTail2 = NULL;int n = 0;printf("請輸入要創建p1和p2鏈表節點個數:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p1 = (pList)malloc(sizeof(struct ListNode));p2 = (pList)malloc(sizeof(struct ListNode));printf("請輸入p1鏈表第%d個節點的值:>", i + 1);scanf("%d", &(p1->val));printf("請輸入p2鏈表第%d個節點的值:>", i + 1);scanf("%d", &(p2->val));p1->next = NULL;p2->next = NULL;if (phead1 == NULL && phead2 == NULL){phead1 = p1;pTail1 = phead1;phead2 = p2;pTail2 = phead2;}else{pTail1->next = p1;pTail1 = pTail1->next;pTail2->next = p2;pTail2 = pTail2->next;}}pList Newhead = mergeTwoLists(phead1,phead2);if (Newhead == NULL){perror("reverselist");return;}pList phead = Newhead;while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已釋放第%d條節點\n", i);i++;}return 0;
}

1.4 鏈表的中間節點

題目要求:

給你單鏈表的頭結點?head?,請你找出并返回鏈表的中間結點。

如果有兩個中間結點,則返回第二個中間結點。

示例 1:

輸入:head = [1,2,3,4,5]
輸出:[3,4,5]
解釋:鏈表只有一個中間結點,值為 3 。

示例 2:

輸入:head = [1,2,3,4,5,6]
輸出:[4,5,6]
解釋:該鏈表有兩個中間結點,值分別為 3 和 4 ,返回第二個結點。

解題思路:

快慢指針:使用快慢指針來遍歷鏈表,慢指針每次走一步,快指針每次走兩步,當快指針走到最后慢指針剛好走到中間節點。因為快指針是慢指針的2倍。所以快指針從起點到終點時慢指針就是這個路程的一半,是中點。

typedef struct ListNode{int val;struct ListNode* next;
}*pList;
//函數實現
struct ListNode* middleNode(struct ListNode* head) {if (head == NULL){return NULL;}struct ListNode* slow, *fast;slow = fast = head;//節點數可能是奇數個也可能是偶數個,所以要兩種判斷while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow;
}

1.5 環形鏈表的約瑟夫問題

著名的Josephus問題

據說著名的歷史學家 Josephus有過以下的故事:故事據說發生在古羅馬時期,在羅馬人占領喬塔帕特后,39個猶太人與約瑟夫及他的朋友躲到一個洞中,他們寧愿死也不要被敵人抓到,于是約定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然后再由下1個人重新報數,直到所有人都自殺身亡為止。

然而Josephus 和他的朋友并不想遵從,Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,于是逃過了這場死亡游戲。

題目要求:

編號為 1?到 n?的 n?個人圍成一圈。從編號為 1?的人開始報數,報到 m?的人離開。

下一個人繼續從 1?開始報數。

n-1 輪結束以后,只剩下一個人,問最后留下的這個人編號是多少?

數據范圍:?1≤𝑛,𝑚≤100001≤n,m≤10000

進階:空間復雜度?𝑂(1)O(1),時間復雜度?𝑂(𝑛)O(n)

示例1

輸入:

5,2     

復制返回值:

3    

復制說明:

開始5個人 1,2,3,4,5 ,從1開始報數,1->1,2->2編號為2的人離開
1,3,4,5,從3開始報數,3->1,4->2編號為4的人離開
1,3,5,從5開始報數,5->1,1->2編號為1的人離開
3,5,從3開始報數,3->1,5->2編號為5的人離開
最后留下人的編號是3      

示例2

輸入:

1,1

返回值:

1
typedef struct ListNode ListNode;創建一個節點并返回
ListNode* ListBuyNode(int val)
{ListNode* ret = (ListNode*)malloc(sizeof(ListNode));if(ret==NULL){perror("malloc");return NULL;}ret->val = val;ret->next = NULL;return ret;
}
//創建一個環形鏈表并返回
ListNode* CreatNode(int n)
{ListNode* phead = ListBuyNode(1);ListNode* pTail = phead;int i = 0;for(i=2;i<=n;i++){pTail->next = ListBuyNode(i);pTail = pTail->next;}pTail->next = phead;//將鏈表循環return pTail;
}int ysf(int n, int m ) {// write code hereListNode* prev = CreatNode(n);ListNode* cur = prev->next;int count = 1;//遍歷判斷while(cur->next!=cur){if(count == m){prev->next = cur->next;free(cur);cur = prev->next;count = 1;}else{prev = cur;cur = cur->next;count++;}}return cur->val;
}

1.6 分隔鏈表

題目要求:

給你一個鏈表的頭節點?head?和一個特定值?x?,請你對鏈表進行分隔,使得所有?小于?x?的節點都出現在?大于或等于?x?的節點之前。

你應當?保留?兩個分區中每個節點的初始相對位置。

示例 1:

輸入:head = [1,4,3,2,5,2], x = 3
輸出:[1,2,2,4,3,5]

示例 2:

輸入:head = [2,1], x = 2
輸出:[1,2]

解題思路:

大小鏈表:我們可以創建兩個新的鏈表,為大小鏈表。遍歷原鏈表。大于等于x的節點連接在大鏈表,小于x的節點連接在小鏈表。最后將大鏈表的頭結點連接在小鏈表的尾結點。返回小鏈表的頭結點

typedef struct ListNode {int val;struct ListNode* next;
}*pList;//分隔鏈表的函數實現
struct ListNode* partition(struct ListNode* head, int x) {if (head == NULL){return NULL;}struct ListNode* lessHead, * lessTail;struct ListNode* greaterHead, * greaterTail;//定義哨兵位lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* pcur = head;//用來遍歷原鏈表//分隔操作while (pcur){if (pcur->val >= x){greaterTail->next = pcur;greaterTail = greaterTail->next;}else{lessTail->next = pcur;lessTail = lessTail->next;}pcur = pcur->next;}//將大小鏈表連接起來lessTail->next = greaterHead->next;if(greaterTail)greaterTail->next = NULL;//釋放哨兵位free(greaterHead);struct ListNode* retList = lessHead->next;free(lessHead);//返回頭結點return retList;
}
int main()
{pList phead, pTail, p;phead = pTail = NULL;int n = 0;printf("請輸入要創建鏈表節點個數:>");scanf("%d", &n);int i = 0;for (i = 0; i < n; i++){p = (pList)malloc(sizeof(struct ListNode));printf("請輸入第%d個節點的值:>", i + 1);scanf("%d", &(p->val));p->next = NULL;if (phead == NULL){phead = p;pTail = phead;}else{pTail->next = p;pTail = pTail->next;}}pList Newhead = partition(phead, 3);if (Newhead == NULL){perror("reverselist");return;}phead = Newhead;while (Newhead){printf("%d->", Newhead->val);Newhead = Newhead->next;}printf("NULL\n");i = 1;Newhead = phead;while (Newhead){phead = phead->next;free(Newhead);Newhead = phead;printf("已釋放第%d條節點\n", i);i++;}return 0;
}

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

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

相關文章

學習java第一百一十八天

Component 和 Bean 的區別是什么&#xff1f;Component 注解作用于類&#xff0c;而Bean注解作用于方法。Component通常是通過類路徑掃描來自動偵測以及自動裝配到 Spring 容器中&#xff08;我們可以使用 ComponentScan 注解定義要掃描的路徑從中找出標識了需要裝配的類自動裝…

Nacos 配置中心:動態加載 Bean

前提&#xff1a; 已經集成好 springboot / cloud 與nacos的環境 1 nacos中配置文件參數 message:#sender: emailMessageSendersender: smsMessageSender 2 接口和兩個實現類 public interface MessageSender {String sendMessage(String message, String recipient); }impo…

模電-二極管及其應用51單片機LED點亮前置工作!

今日小記 2024-7-2&#xff0c;星期二&#xff0c;16:32&#xff0c;天氣&#xff1a;晴&#xff0c;心情&#xff1a;晴。持續了兩個星期的梅雨天終于暫時過去啦&#xff0c;迎來了久違的陽光&#xff0c;雖然沒有雨天涼快&#xff0c;但是能看到太陽也是開心噠&#xff0c;心…

2021強網杯

一、環境 網上自己找 二、步驟 2.1拋出引題 在這個代碼中我們反序列&#xff0c;再序列化 <?php$raw O:1:"A":1:{s:1:"a";s:1:"b";};echo serialize(unserialize($raw));//O:1:"A":1:{s:1:"a";s:1:"b";…

工業 web4.0UI 風格品質卓越

工業 web4.0UI 風格品質卓越

深入理解 RabbitMQ、RocketMQ等常?的消息中間件進?消息的異步數據處理

深入理解消息中間件對于構建高可用、高性能的分布式系統至關重要。以下是對RabbitMQ和RocketMQ這兩種常用消息中間件的異步數據處理的深入理解&#xff1a; ### RabbitMQ RabbitMQ是一個開源的消息代理&#xff0c;它支持多種消息協議&#xff0c;如AMQP、STOMP等&#xff0c;…

單向鏈表結構

鏈表結構簡介 鏈表結構是一種用比較特殊的數據結構類型&#xff0c;它也是線性數據結構中的一種&#xff0c;但是與棧結構等線性數據結構不同&#xff0c;它的內部結構并不是一個簡單的存儲空間&#xff0c;而是一個帶有指向性質的單元。要理解鏈表結構要弄清楚兩個問題&#x…

不要再被騙了!電腦無法進入系統的原因可能是這個硬件壞了而已……

前言 前段時間小白在抖音上發了很多很多很多的視頻&#xff0c;其中應該是有很多商家關注了小白。 然后就會出現很多很多很多的賺錢小門道…… 電腦開機沒有顯示&#xff1f;換顯卡&#xff01; 電腦還是不開機&#xff1f;換CPU 電腦還是一樣不開機…… 經過了一番大折騰…

10.8K star!史上最強Web應用防火墻雷池WAF

長亭雷池SafeLine是長亭科技耗時近 10 年傾情打造的WAF(Web Application Firewall)&#xff0c; 一款敢打出口號 “不讓黑客越雷池一步” 的 WAF&#xff0c;愿稱之為史上最強的一款Web應用防火墻&#xff0c;足夠簡單、足夠好用、足夠強的免費且開源的 WAF&#xff0c;基于業…

AI為小微企業賦能:解鎖數字化轉型的金鑰匙

AI為小微企業賦能&#xff1a;解鎖數字化轉型的金鑰匙 在當今全球經濟加速迭代的背景下&#xff0c;小微企業作為社會經濟肌體的毛細血管&#xff0c;面臨著前所未有的挑戰與機遇。人工智能&#xff08;AI&#xff09;的崛起&#xff0c;如同一股強大的科技旋風&#xff0c;為…

binlog區分業務修改還是手動修改

一、Windows下開啟MySQL binLog日志 首先要開啟MySQL的BinLog 管理 show variables like %log_bin%;如果發現log_bin是OFF&#xff0c;打開mysql文件夾下面的my.ini&#xff0c;修改一下 在 [mysqld] 下面加 # 開啟bin-log log-binmysql-bin # 開啟binlog功能 binl…

pads layout 腳本導出不能運行excle解決辦法

在一臺新的電腦上安裝好PADS&#xff0c;打開PCB文件導出坐標文件時&#xff1a; 出現“ActiveX Automation: server could not be found.”的問題,導致無法成功導出文件,錯誤提示截圖如下&#xff1a; 導致上述問題的原因是在我們配置導出帶坐標的腳本時,默認使用的是微軟…

Java 實現application/x-www-form-urlencoded編碼格式的POST請求

一、實現方式 在Java中&#xff0c;實現application/x-www-form-urlencoded內容類型通常涉及到發送HTTP POST請求。你可以使用java.net.HttpURLConnection或者第三方庫如Apache HttpClient來實現。 以下是使用HttpURLConnection發送application/x-www-form-urlencoded數據的代…

linux的shell腳本編程詳解

Shell 腳本是一種用于自動化任務的腳本語言&#xff0c;在 Linux 和其他類 Unix 操作系統中非常流行。它通常用于任務自動化、系統管理和批處理。編寫 Shell 腳本并使其自動化編譯過程&#xff08;例如使用 gcc 編譯 C/C 程序&#xff09;是一種常見的任務。 以下是一個詳細的…

昇思MindSpore學習筆記3--張量 Tensor

一、張量Tensor概念 矢量、標量和其他張量的計算函數&#xff0c;有內積、外積、線性映射以及笛卡兒積等 張量坐標在 n?維空間內&#xff0c;有?nr 個分量 每個分量都是坐標的函數,變換時每個坐標分量都按規則作線性變換 張量是一種特殊的數據結構&#xff0c;類似于數組和…

利用深度學習模型進行語音障礙自動評估

語音的產生涉及器官的復雜協調&#xff0c;因此&#xff0c;語音包含了有關身體各個方面的信息&#xff0c;從認知狀態和心理狀態到呼吸條件。近十年來&#xff0c;研究者致力于發現和利用語音生物標志物——即與特定疾病相關的語音特征&#xff0c;用于診斷。隨著人工智能&…

js基礎學習

1、js概述 js是javascript的簡稱&#xff0c;作用是實現頁面和用戶的交互 js由瀏覽器解析運行&#xff0c;不需要編譯 js由es基礎語法&#xff0c;bom瀏覽器相關&#xff0c;dom文檔操作相關 三大部分組成 2、html引入js <!DOCTYPE html> <html lang"zh-CN&qu…

Vue項目打包上線

Nginx 是一個高性能的開源HTTP和反向代理服務器&#xff0c;也是一個IMAP/POP3/SMTP代理服務器。它在設計上旨在處理高并發的請求&#xff0c;是一個輕量級、高效能的Web服務器和反向代理服務器&#xff0c;廣泛用于提供靜態資源、負載均衡、反向代理等功能。 1、下載nginx 2、…

k8s學習--k8s群集ELK日志收集部署最詳細的過程與應用(收集k8s群集日志)(圖形化界面手把手教學)

文章目錄 FilebeatFilebeat主要特點Filebeat使用場景 ELK簡介Elasticsearch簡介Elasticsearch主要特點Elasticsearch使用場景 Logstash簡介Logstash主要特點Logstash使用場景 Kibana簡介Kibana主要特點Kibana使用場景 簡單理解 環境一、ELK集群部署1.軟件安裝2.軟件配置及啟動(…

Webpack: Loader開發 (2)

概述 在上一篇文章中&#xff0c;我們已經詳細了解了開發 Webpack Loader 需要用到的基本技能&#xff0c;包括&#xff1a;Loader 基本形態、如何構建測試環境、如何使用 Loader Context 接口等。接下來我們繼續拓展學習一些 Loader 輔助工具&#xff0c;包括&#xff1a; 了…