image.png
image.png

解法一:迭代

在做题之前需要分析一下链表有多少种情况:

  1. 链表没有元素
  2. 链表只有一个元素
  3. 链表的元素个数为奇数
  4. 链表的元素个数为偶数

当 head 为 null 或者只有一个元素的时候,由于没有可以交换的节点,因此直接返回 head 就可以了。而对于节点超过一个的情况,在处理的时候,就应该将节点两两组合进行处理,也就是说:

  1. function swapPairs(head: ListNode | null): ListNode | null {
  2. let result = head
  3. let prev = null
  4. let currentNode = head
  5. while(currentNode && currentNode.next) {
  6. // 如果当前节点为头节点,则应该保存它的下一个节点,因为交换之后,原来的第二个节点变成链表的头节点,
  7. // 因此需要将这个链表的新的头部作为结果返回。
  8. if (currentNode === head) {
  9. result = currentNode.next
  10. }
  11. // 将当前节点与后一个节点进行交换
  12. const nextNode = currentNode.next
  13. currentNode.next = nextNode.next
  14. nextNode.next = currentNode
  15. // 如果记录了前一个节点,则应该将前一个节点的 next 更改为交换后的节点
  16. if (prev) {
  17. prev.next = nextNode
  18. }
  19. prev = currentNode
  20. currentNode = currentNode.next
  21. }
  22. return result
  23. };

上面的解法中,迭代中的逻辑需要有一个判断当前节点是否为头节点的逻辑,以及判断是否记录了 prev 的逻辑。这里可以使用虚拟头节点来省略判断的逻辑:

  1. function swapPairs(head: ListNode | null): ListNode | null {
  2. let dummyHead = new ListNode(0, head)
  3. let prev: ListNode = dummyHead
  4. let currentNode: ListNode | null = dummyHead.next
  5. while(currentNode && currentNode.next) {
  6. // 交换当前这一轮的两个节点位置
  7. const nextNode = currentNode.next
  8. currentNode.next = nextNode.next
  9. nextNode.next = currentNode
  10. // 更新上一轮最后一个节点的 next
  11. prev.next = nextNode
  12. prev = currentNode
  13. currentNode = currentNode.next
  14. }
  15. return dummyHead.next
  16. }

解法二:递归

  1. function swapPairs(head: ListNode | null): ListNode | null {
  2. // 链表为空
  3. // 链表节点数只有一个
  4. // 链表节点数为奇数
  5. // 链表节点数为偶数
  6. if (head === null || head.next === null) {
  7. return head
  8. }
  9. const nextNode = head.next
  10. head.next = swapPairs(nextNode.next)
  11. nextNode.next = head
  12. return nextNode
  13. };