目錄
1. 移除鏈表元素
1.1 題目描述及鏈接
1.2 解題思路
1.3 程序
2. 反轉鏈表
2.1 題目描述及鏈接
2.2 解題思路
2.3 程序
3. 鏈表的中間結點
3.1 題目描述及鏈接
3.2 解題思路
3.3 程序
1. 移除鏈表元素
1.1 題目描述及鏈接
原題鏈接:203. 移除鏈表元素 - 力扣(LeetCode)
題目描述:給你一個鏈表的頭節點 head 和一個整數 val ,
請你刪除鏈表中所有滿足 Node.val == val 的節點,并返回 新的頭節點 。
1.2 解題思路
思路1:創建一個新鏈表,遍歷原鏈表,將 Node.val != val的結點均尾插到新鏈表中。
思路2:創建鏈表結點curNode遍歷鏈表,并對應記錄該結點的前驅結點與后繼結點,刪除該結點后再對其余結點進行鏈接。
1.3 程序
以思路1為例:
1、創建新鏈表首先定義一個結點作為新鏈表的頭結點newHead,且須作為方法的返回值返回;
2、遍歷原鏈表判斷當前結點的val值,需定義一個結構體指針curNode用于遍歷原鏈表。
3、由于需將Node.val !=val的結點尾插至新鏈表,故需定義結構體指針變量newTail指向新鏈表的最后一個結。并在最后完成尾插后將newTail的后繼指針域置為NULL;
4、考慮特殊情況及相應處理:
(1)原鏈表為空:即head=NULL,導致curNode=NULL,不會進入第一個while循環,但在newTail->next=NULL 時會導致空指針解引用操作,出現錯誤。故需對newTail是否為空進行單獨討論處理。
(2)新鏈表為空:即原鏈表所有結點數據域的值都等于val,導致newTail->next=NULL 時會導致空指針解引用操作,出現錯誤。同(1):需對newTail是否為空進行單獨討論處理。
處理邏輯為:
若newTail為空,再newTail->next=NULL,否則直接返回newHead(newHead也為空);
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {// 創建一個空鏈表ListNode* newHead=NULL;ListNode* newTail=NULL;ListNode* curNode=head;while(curNode){if(curNode->val!=val){// 情況1:鏈表為空if(newHead==NULL){newHead=curNode;newTail=curNode;}// 情況2:鏈表不為空else{newTail->next=curNode;newTail=newTail->next;}}curNode=curNode->next;}// 將新鏈表尾結點的后繼指針置空// 討論新鏈表為空與非空的兩種情況if(newTail){newTail->next=NULL;}return newHead;
}
2. 反轉鏈表
2.1 題目描述及鏈接
題目鏈接:206. 反轉鏈表 - 力扣(LeetCode)
題目描述:給你單鏈表的頭節點 head ,請你反轉鏈表,并返回反轉后的鏈表。
2.2 解題思路
思路1:
創建一個新的鏈表,并定義頭結點指針newHead和尾結點指針newNode,遍歷原鏈表,依次取當前結點頭插到新鏈表中。
思路2:
無需創建新鏈表,創建三個指針,用于逐個逆轉指針指向。
2.3 程序
以思路2為例:
創建三個指針變量。初始情況下,令n1指向空,n2指向原鏈表的頭結點,n3指向原鏈表頭結點的下一個結點。
以n2作為修改當前指向結點的后繼指針域指向的用于遍歷的結構體指針,逐個翻轉指針域指向。再令n1、n2、n3依次后移。
考慮最終情況,n3最先變為空指針,直至n2指向原鏈表的最后一個結點完成指針域的指向反轉后,表示當前鏈表已完成反轉操作,故循環條件為n2不為空。
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {// 判空if(head==NULL){return head;}// 創建三個指針ListNode* n1=NULL;ListNode* n2=head;ListNode* n3=n2->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3)n3=n3->next;}return n1;
}
3. 鏈表的中間結點
3.1 題目描述及鏈接
題目鏈接:876. 鏈表的中間結點 - 力扣(LeetCode)
題目描述:
給你單鏈表的頭結點 head ,請你找出并返回鏈表的中間結點。
如果有兩個中間結點,則返回第二個中間結點。
3.2 解題思路
思路1:
遍歷原鏈表,使用count計數,count/2位置結點的下一個結點就是滿足條件的中間結點,可返回count/2位置結點的后繼指針即可。
思路2:快慢指針
創建兩個結構體指針變量,令一個指針每次走一步,另外一個指針每次走兩步,走得快的指針稱為fast快指針,走得慢的指針稱為slow慢指針。
3.3 程序
以思路二為例:考慮循環條件。
對于奇數個結點的鏈表,當fast->next=NULL時,slow正指向中間結點;
對于偶數個結點的鏈表,當fast=NULL時,slow正指向兩個中間結點的后一個節點;
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {ListNode* slow=head;ListNode* fast=head;while(fast!=NULL&&fast->next!=NULL){fast=fast->next->next;slow=slow->next;}return slow;
}
注:對于循環條件while(fast!=NULL&&fast->next!=NULL)不可更改為
while(fast->next!=NULL&&fast!=NULL),由于在偶數個結點的鏈表中,當fast==NULL時,slow正指向兩個中間結點的后一個,此種情況下,若交換順序則會導致對空指針的解引用,出錯。
由于邏輯與具有短路特性,若已驗證操作符左側表達式為假,則不再驗右側表達式真假。