方法一:迭代
我們把鏈表分爲兩部分,即奇數節點爲一部分,偶數節點爲一部分,A 指的是交換節點中的前面的節點,B 指的是要交換節點中的後面的節點。在完成它們的交換,我們還得用 prevNode 記錄 A 的前驅節點。
算法:
1.firstNode(即 A) 和 secondNode(即 B) 分別遍歷偶數節點和奇數節點,即兩步看作一步。
2.交換兩個節點:
firstNode.next = secondNode.next
secondNode.next = firstNode
3.還需要更新 prevNode.next 指向交換後的頭。
prevNode.next = secondNode
4.迭代完成後得到最終的交換結果。
class Solution {
public ListNode swapPairs(ListNode head) {
// Dummy node acts as the prevNode for the head node
// of the list and hence stores pointer to the head node.
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode prevNode = dummy;
while ((head != null) && (head.next != null)) {
// Nodes to be swapped
ListNode firstNode = head;
ListNode secondNode = head.next;
// Swapping
prevNode.next = secondNode;
firstNode.next = secondNode.next;
secondNode.next = firstNode;
// Reinitializing the head and prevNode for next swap
prevNode = firstNode;
head = firstNode.next; // jump
}
// Return the new head node.
return dummy.next;
}
}
複雜度分析
時間複雜度:O(N),其中 NN 指的是鏈表的節點數量。
空間複雜度:O(1)
方法二:遞歸
算法:
1從鏈表的頭節點 head 開始遞歸。
2 每次遞歸都負責交換一對節點。由 firstNode 和 secondNode 表示要交換的兩個節點。
3下一次遞歸則是傳遞的是下一對需要交換的節點。
4 若鏈表中還有節點,則繼續遞歸。 交換了兩個節點以後,返回
secondNode,因爲它是交換後的新頭。
5 在所有節點交換完成以後,我們返回交換後的頭,實際上是原始鏈表的第二個節點。
class Solution {
public ListNode swapPairs(ListNode head) {
// If the list has no node or has only one node left.
if ((head == null) || (head.next == null)) {
return head;
}
// Nodes to be swapped
ListNode firstNode = head;
ListNode secondNode = head.next;
// Swapping
firstNode.next = swapPairs(secondNode.next);
secondNode.next = firstNode;
// Now the head is the second node
return secondNode;
}
}
複雜度分析
時間複雜度:O(N),其中 N指的是鏈表的節點數量。
空間複雜度:O(N),遞歸過程使用的堆棧空間。