Problem: 24. 两两交换链表中的节点
方法一:迭代
思路
设置一个哑结点 d u m m y dummy dummy, d u m m y → n e x t = h e a d dummy \rightarrow next = head dummy→next=head,最终结果 d u m m y − > n e x t dummy->next dummy−>next。
设置结点 c u r cur cur遍历整个链表, c u r cur cur初始位置在 d u m m y dummy dummy。当 c u r cur cur之后存在两个结点则需要交换,分别设为 n o d e 1 node1 node1、 n o d e 2 node2 node2。此时三个结点的关系: c u r → n o d e 1 → n o d e 2 → . . . cur \rightarrow node1 \rightarrow node2 \rightarrow ... cur→node1→node2→...
执行交换操作得到 c u r → n o d e 2 → n o d e 1 → . . . cur \rightarrow node2 \rightarrow node1 \rightarrow ... cur→node2→node1→...
c u r → n e x t = n o d e 2 cur \rightarrow next = node2 cur→next=node2
n o d e 1 → n e x t = n o d e 2 → n e x t node1 \rightarrow next = node2 \rightarrow next node1→next=node2→next
n o d e 2 → n e x t = n o d e 1 node2 \rightarrow next = node1 node2→next=node1
将 c u r = n o d e 1 cur = node1 cur=node1进行下一次遍历,当 c u r cur cur之后无两个结点则无需交换跳出循环,返回结果。
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummy = new ListNode(-1, head);
ListNode* cur = dummy;
while(cur->next && cur->next->next){ //当之后存在两个节点
ListNode* node1 = cur->next, *node2 = cur->next->next;
cur->next = node2;
node1->next = node2->next;
node2->next = node1;
cur = node1;
}
return dummy->next;
}
};
复杂度
-
时间复杂度:
O ( n ) O(n) O(n), n n n为链表长度。 -
空间复杂度:
O ( 1 ) O(1) O(1)
方法二:递归
思路
链表的问题往往可以使用递归来解决,递归问题的思考可以拆分成两个部分去思考,即递和归。
- 递 :将原问题拆分成相似的子问题,子问题与问题相似且比原问题规模更小,不断拆分后会有一个尽头,即递归边界条件。
- 子问题:将前两个结点进行交换,第三个结点递归交换。 n o d e 1 → n o d e 2 → n o d e 3 → . . . node1 \rightarrow node2 \rightarrow node3 \rightarrow... node1→node2→node3→...转换为 n o d e 2 → n o d e 1 → n o d e 3 → . . . node2 \rightarrow node1 \rightarrow node3 \rightarrow ... node2→node1→node3→..., n o d e 3 node3 node3的交换可以通过递归来解决。
- 递归的边界条件:链表中没有结点,或者链表中只有一个结点,不需要交换。
- 归:返回交换后的头结点。
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//递归边界条件, 有2个结点才需要交换
if(head == nullptr || head->next == nullptr){
return head;
}
ListNode* newHead = head->next;
head->next = swapPairs(newHead->next);
newHead->next = head;
return newHead;
}
};
复杂度
-
时间复杂度:
O ( n ) O(n) O(n), n n n为链表长度。 -
空间复杂度:
O ( n ) O(n) O(n), n n n为链表长度。