---
# System prepended metadata

title: Swap Nodes in Pairs

---

# Swap Nodes in Pairs

## 解題流程

### 1. 釐清input, output
- input 為 `ListNode` (linked list)
- output 為 `ListNode` (經過兩兩成對反轉後的linked list)

(e.g. 若input為: `1 -> 2 -> 3 -> 4`，則output為: `2 -> 1 -> 4 -> 3`)

### 2. 列出constraints與edge cases
- constraints: 嘗試達到時間複雜度 O(n)，n為`ListNode`數量，空間複雜度 O(1)
- edge cases: 
  1. 空的linked list，應回傳`null`/`undefined`
  2. 奇數個節點的linked list
    - input為: `1`，則output亦為：`1`
    - input為: `1 -> 2 -> 3`，則output應為： `2 -> 1 -> 3`

### 3. 解題思路

觀察到linked list是兩兩成對反轉，試著divie and conquer，先從第一對的反轉著手：

- **step1.** 將 `2` 指向 `1`， `1` 指向 `3`

  原本: 
  `1 -> 2 -> 3 -> 4 -> 5 -> 6`
  結果: 
  `2 -> 1 -> 3 -> 4 -> 5 -> 6`

- **step2.** 將 `1` 指向 `4` 

  原本：
  `2 -> 1 -> 3 -> 4 -> 5 -> 6`

  結果：
  ```
  2 -> 1
       |
       V
  3 -> 4 -> 5 -> 6            
  ```

  這時候發現 `3 -> 4 -> 5 -> 6` 跟原本 `1 -> 2 -> 3 -> 4` 是一樣的pattern。



- 接下來執行像 **step1.** 一樣的操作， `4` 要指向 `3`， `3` 指向 `5`。
原本：
  ```
  2 -> 1
       |
       V
  3 -> 4 -> 5 -> 6            
  ```

  結果： 
  `2 -> 1 -> 4 -> 3 -> 5 -> 6`


- 再來執行像 **step2.** 一樣的操作， `3` 要指向 `6`
  原本：
  `2 -> 1 -> 4 -> 3 -> 5 -> 6`

  結果：
  ```
  2 -> 1 -> 4 -> 3
                 |
                 V
            5 -> 6 -> 7 -> 8            
  ```




- 到這邊已經觀察到相同pattern的出現，基本上就是重複**step1.** 跟 **step2.** 的操作，直到遇上`null`/`undefined`的`ListNode`。
- 接著將這樣的操作過程用程式碼寫出來。


### 4. 程式碼

- 初步寫出來會是這樣：
```javascript=
let first = head;
let second = head?.next;
let third = second?.next;
let fourth = third?.next;


while (first != null && second != null) {
  // step1.
  second.next = first; // 將 2 指向 1 
  first.next = third; // 將 1 指向 3

  // 如果4是空的時候，1繼續指向3(這個情形是奇數個節點的linked list)
  if (fourth != null) {
    // step2.
    first.next = fourth; // 將 1 指向 4
  }

  first = third;
  second = fourth;
  third = second?.next;
  fourth = third?.next;
}
    
```
- 但會有一個問題，最後必須回傳linked list的head，目前程式碼沒有處理到這件事。於是增加第8.行跟第24.行：
```javascript=
let first = head;
let second = head?.next;
let third = second?.next;
let fourth = third?.next;

// 因為經過翻轉，所以新的head會是原本第二個節點，不是原本第一個節點
// 但如果linked list只有一個節點的話，新的head一樣會是原本的第一個節點
let newHead = second ?? first; 

while (first != null && second != null) {
  second.next = first; 
  first.next = third; 

  if (fourth != null) {
    first.next = fourth; 
  }
      
  first = third;
  second = fourth;
  third = second?.next;
  fourth = third?.next;
}

return newHead;
```

- 最後leetcode上的程式碼長這樣：
```javascript=
var swapPairs = function(head) {
  let first = head;
  let second = head?.next;
  let third = second?.next;
  let fourth = third?.next;

  let newHead = second ?? first; 

  while (first != null && second != null) {
    second.next = first; 
    first.next = third; 
      
    if (fourth != null) {
      first.next = fourth; 
    }
      
    first = third;
    second = fourth;
    third = second?.next;
    fourth = third?.next;
  }

  return newHead;
}
```

### 5. 驗證
- leetcode測試通過，且 [edge cases](#2.-列出constraints與edge-cases) 有過關。
- 時間複雜度為O(n)：因為單個節點只會被操作constant的次數
- 空間複雜度為O(1)：因為並沒有額外建立反映linked list大小的記憶體







