問題詳情
Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
結點結構爲:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
問題分析及思路
最近忙期中的事,大概已經半個多月沒有碰過leetcode了,這是新的一道題,後面會多打一些。
這道題大致意思是將一個鏈表中相鄰兩個結點相交換,但是不能直接交換它們的值,必須交換它們的結點。剛開始接觸這道題我嘗試用一個while循環來做它,卻發現非常複雜,幾乎寫不出while循環來實現它。
認真思考後我發現這是一個遞歸問題,正好遞歸一直是我的弱項,這道題可以鍛鍊我的遞歸能力。
最後算法思路如下:
1.對函數swapTwoPairs傳入一個結點First,當First的下下個結點不爲空時,用結點Second保存它的下下個結點,Third保存它的下一個結點。使得First的下下個結點變爲它自己,First的下個結點變爲swapTwoPairs(Second)遞歸。遞歸完成後返回Third。
2.當First的下下個結點爲空時,用Third保存它的下個結點,使得First的下下個結點變爲它自己,它的下個結點爲NULL,返回Third。
以上算法思路有漏洞,只考慮了有偶數個結點的情況,沒有考慮爲奇數個結點的情況,故在算法前還要加一個判斷:
如果First的下個結點爲NULL,則直接返回First。
此外還要注意,當傳入一個空的鏈表時,還要檢查是否爲空。爲空就不進入遞歸,直接返回NULL。
由於本人對遞歸十分不熟悉,這道題收穫很多,它的遞歸次數大概是n個結點數除以2,即log2n次,時間複雜度爲O((log2n)2)。
具體代碼
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head == NULL) {
return NULL;
}
return swapTwoPairs(head);
}
ListNode* swapTwoPairs(ListNode* First) {
if(First->next == NULL) {
return First;
}
if(First->next->next != NULL) {
ListNode* Second = First->next->next;
ListNode* Third = First->next;
First->next->next = First;
First->next = swapTwoPairs(Second);
return Third;
} else {
First->next->next = First;
ListNode* Third = First->next;
First->next = NULL;
return Third;
}
}
};