wordpress評論框加游戲優(yōu)化大師官方下載
1兩兩交換鏈表中的節(jié)點
給你一個鏈表,兩兩交換其中相鄰的節(jié)點,并返回交換后鏈表的頭節(jié)點。你必須在不修改節(jié)點內(nèi)部的值的情況下完成本題(即,只能進(jìn)行節(jié)點交換)。
示例 1:
輸入:head = [1,2,3,4] 輸出:[2,1,4,3]
示例 2:
輸入:head = [] 輸出:[]
示例 3:
輸入:head = [1] 輸出:[1]
提示:
- 鏈表中節(jié)點的數(shù)目在范圍?
[0, 100]
?內(nèi) 0 <= Node.val <= 100
思路:
初始檢查:如果鏈表為空或只有一個節(jié)點,直接返回。
創(chuàng)建虛擬頭節(jié)點:使用一個虛擬頭節(jié)點 dummy 來簡化邊界情況的處理。
循環(huán)交換節(jié)點對:在鏈表中繼續(xù)交換每一對節(jié)點,直到?jīng)]有更多的節(jié)點對(cur->next && cur->next->next 都不為空時)可以交換。開始時cur為與虛擬頭結(jié)點位置
步驟一:cur->next 指向第二個節(jié)點。
步驟二:第二個節(jié)點的 next 指向第一個節(jié)點。
步驟三:第一個節(jié)點的 next 指向第三個節(jié)點。
移動到下一對節(jié)點的前一個節(jié)點:將 cur 移動到下一對節(jié)點的前一個節(jié)點。
代碼:
struct ListNode* swapPairs(struct ListNode* head) {// 如果鏈表為空或只有一個節(jié)點,直接返回if (!head || !head->next) return head;struct ListNode dummy; // 創(chuàng)建一個虛擬頭節(jié)點dummy.next = head;struct ListNode* cur = &dummy;while (cur->next && cur->next->next) {struct ListNode* tmp = cur->next; // 保存第一個節(jié)點struct ListNode* tmp1 = cur->next->next->next; // 保存第二個節(jié)點的下一個節(jié)點cur->next = cur->next->next; // 步驟一:cur->next 指向第二個節(jié)點cur->next->next = tmp; // 步驟二:第二個節(jié)點的 next 指向第一個節(jié)點cur->next->next->next = tmp1; // 步驟三:第一個節(jié)點的 next 指向第三個節(jié)點cur = cur->next->next; // 移動到下一對節(jié)點的前一個節(jié)點}return dummy.next; // 返回新的頭節(jié)點
}
2刪除鏈表的倒數(shù)第 N 個結(jié)點
給你一個鏈表,刪除鏈表的倒數(shù)第?n
?個結(jié)點,并且返回鏈表的頭結(jié)點。
示例 1:
輸入:head = [1,2,3,4,5], n = 2 輸出:[1,2,3,5]
示例 2:
輸入:head = [1], n = 1 輸出:[]
示例 3:
輸入:head = [1,2], n = 1 輸出:[1]
提示:
- 鏈表中結(jié)點的數(shù)目為?
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
思路:
- 創(chuàng)建虛擬頭節(jié)點:使用?
malloc
?分配內(nèi)存并創(chuàng)建一個虛擬頭節(jié)點?dummy
,其?val
?為 0,next
?指向?qū)嶋H的頭節(jié)點?head
。 - 初始化快慢指針:
fast
?和?slow
?都指向虛擬頭節(jié)點。 - 快指針先移動 n 步:通過循環(huán),讓?
fast
?指針先移動?n
?步。 - 快指針再移動一步:因為需要讓slow指向刪除節(jié)點的上一個節(jié)點
- 同時移動快慢指針:繼續(xù)移動?
fast
?和?slow
?指針,直到?fast
?指針到達(dá)鏈表末尾。此時,slow
?指針指向的節(jié)點就是要刪除的節(jié)點的前一個節(jié)點。 - 刪除節(jié)點:將?
slow
?的?next
?指向?slow->next->next
,從而刪除目標(biāo)節(jié)點。 - 更新頭節(jié)點:將?
head
?更新為?dummy->next
。 - 釋放虛擬頭節(jié)點:使用?
free
?釋放虛擬頭節(jié)點的內(nèi)存空間。 - 返回頭節(jié)點:返回更新后的頭節(jié)點?
head
。
代碼:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {// 創(chuàng)建一個虛擬頭節(jié)點,并初始化其值為0,next指向?qū)嶋H的頭節(jié)點struct ListNode* dummy = malloc(sizeof(struct ListNode));dummy->val = 0;dummy->next = head;// 初始化快慢指針,都指向虛擬頭節(jié)點struct ListNode* fast = dummy;struct ListNode* slow = dummy;// 快指針先向前移動n步for (int i = 0; i < n; i++) {fast = fast->next;}// fast再提前走一步,因為需要讓slow指向刪除節(jié)點的上一個節(jié)點fast = fast->next;// 快慢指針同時移動,直到快指針到達(dá)鏈表末尾while (fast) {fast = fast->next;slow = slow->next;}// 刪除慢指針的下一個節(jié)點(即倒數(shù)第n個節(jié)點)slow->next = slow->next->next;// 更新頭節(jié)點(dummy是虛擬頭節(jié)點,刪除操作不會影響head)head = dummy->next;// 釋放虛擬頭節(jié)點的內(nèi)存(注意:這里應(yīng)該釋放dummy,而不是釋放dummy->next,因為dummy->next是實際的鏈表節(jié)點)free(dummy);// 返回更新后的頭節(jié)點return head;
}
3鏈表相交
給你兩個單鏈表的頭節(jié)點?headA
?和?headB
?,請你找出并返回兩個單鏈表相交的起始節(jié)點。如果兩個鏈表沒有交點,返回?null
?。
圖示兩個鏈表在節(jié)點?c1
?開始相交:
題目數(shù)據(jù)?保證?整個鏈?zhǔn)浇Y(jié)構(gòu)中不存在環(huán)。
注意,函數(shù)返回結(jié)果后,鏈表必須?保持其原始結(jié)構(gòu)?。
示例 1:
輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 輸出:Intersected at '8' 解釋:相交節(jié)點的值為 8 (注意,如果兩個鏈表相交則不能為 0)。 從各自的表頭開始算起,鏈表 A 為 [4,1,8,4,5],鏈表 B 為 [5,0,1,8,4,5]。 在 A 中,相交節(jié)點前有 2 個節(jié)點;在 B 中,相交節(jié)點前有 3 個節(jié)點。
示例?2:
輸入:intersectVal?= 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 輸出:Intersected at '2' 解釋:相交節(jié)點的值為 2 (注意,如果兩個鏈表相交則不能為 0)。 從各自的表頭開始算起,鏈表 A 為 [0,9,1,2,4],鏈表 B 為 [3,2,4]。 在 A 中,相交節(jié)點前有 3 個節(jié)點;在 B 中,相交節(jié)點前有 1 個節(jié)點。
示例?3:
輸入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 輸出:null 解釋:從各自的表頭開始算起,鏈表 A 為 [2,6,4],鏈表 B 為 [1,5]。 由于這兩個鏈表不相交,所以 intersectVal 必須為 0,而 skipA 和 skipB 可以是任意值。 這兩個鏈表不相交,因此返回 null 。
提示:
listA
?中節(jié)點數(shù)目為?m
listB
?中節(jié)點數(shù)目為?n
0 <= m, n <= 3 * 104
1 <= Node.val <= 105
0 <= skipA <= m
0 <= skipB <= n
- 如果?
listA
?和?listB
?沒有交點,intersectVal
?為?0
- 如果?
listA
?和?listB
?有交點,intersectVal == listA[skipA + 1] == listB[skipB + 1]
思路:
- 初始化變量:定義?
longList
?和?shortList
?用于存儲長鏈表和短鏈表的頭節(jié)點,lenA
?和?lenB
?用于存儲兩個鏈表的長度,gap
?用于存儲長度差。 - 計算鏈表長度:通過遍歷鏈表?
headA
?和?headB
,分別計算它們的長度?lenA
?和?lenB
。 - 確定長鏈表和短鏈表:通過比較?
lenA
?和?lenB
,確定哪個是長鏈表,哪個是短鏈表,并計算長度差?gap
。 - 尾部對齊:將長鏈表?
longList
?移動?gap
?步,使得兩個鏈表的尾部對齊。 - 同時移動并檢查交點:同時移動?
longList
?和?shortList
,檢查是否有相同的節(jié)點。如果找到相同的節(jié)點,則返回該節(jié)點(即交點)。 - 返回結(jié)果:如果沒有找到交點,則返回?
NULL
。
代碼:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode *longList = NULL, *shortList = NULL;int lenA = 0, lenB = 0, gap = 0;// 求出兩個鏈表的長度shortList = headA;while (shortList) {lenA++;shortList = shortList->next;}shortList = headB;while (shortList) {lenB++;shortList = shortList->next;}// 確定長鏈表和短鏈表,并計算長度差if (lenA > lenB) {longList = headA;shortList = headB;gap = lenA - lenB;} else {longList = headB;shortList = headA;gap = lenB - lenA;}// 將長鏈表和短鏈表的尾部對齊while (gap--) {longList = longList->next;}// 同時移動長鏈表和短鏈表,檢查是否有相同的節(jié)點while (longList) {if (longList == shortList) return longList; // 找到交點longList = longList->next;shortList = shortList->next;}// 沒有找到交點return NULL;
}