24 两两交换链表中的节点(2021.07.21)

这篇博客探讨了如何解决LeetCode的第24题——两两交换链表中的节点。作者分享了三种解法,包括迭代、递归和使用栈的方法,并分别提供了详细的实现思路和执行效率分析。每种方法都避免了特殊情况的处理,且迭代和递归解法在执行时间和空间复杂度上表现出色。
摘要由CSDN通过智能技术生成

24. 两两交换链表中的节点

链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs/

题目描述见链接内容。

解法1:迭代

一开始想用双指针解决,结果把两个指针一顿交换,发现交换了个寂寞,后来发现只利用一个指针cur,对cur.nextcur.next.next不断赋值就可以

还利用之前的小技巧,声明了一个DummyNode,放在head前面,这样就不需要判断首节点的特殊性了

var swapPairs = function (head) {
  // 在 head 之前声明一个DummyNode
  const dummyNode = new ListNode();
  dummyNode.next = head;

  let cur = dummyNode;

  // dummyNode head node1 node2 node3....
  while (cur && cur.next && cur.next.next) {
    // cur 指向 dummyNode, next 变量指向 node2
    const next = cur.next && cur.next.next ? cur.next.next.next : null,
      // prev 指向 head
      prev = cur.next;

    // 将 dummyNode.next  指向 node1
    cur.next = cur.next ? cur.next.next : null;
    // 将新的 node1.next 指向 head,实现了换位
    cur.next.next = prev;
    // 将换位后的 head.next 指向 node2,把断开的链表又练了起来
    cur.next.next.next = next;

    // 指针需要向前移动两位
    cur = cur.next ? cur.next.next : null;
  }

  return dummyNode.next;
};
  • 时间复杂度:${O(N)}$
  • 空间复杂度:${O(1)}$
  • 执行用时:68ms, 在所有JavaScript提交中击败了95%的用户,内存消耗:37.7MB,在所有JavaScript提交中击败了91%的用户

解法2:递归

为什么我总是想不到递归的解法,看了题解发现又很简单,可以参考这篇文章,好好学习一下递归

关于这道题的解决,只要参考下面一张图就能够搞明白了:

var swapPairs = function (head) {
  if (!head || !head.next) {
    return head;
  }

  // 原来的后面的节点
  const next = head.next;
  
  // head 移动到后面后,需要连接的已处理完成的节点
  head.next = swapPairs(next.next);
  
  // 将 next 移动到 head 前面
  next.next = head;
  
  // 返回的是已处理好的节点
  return next;
};
  • 时间复杂度:${O(N)}$
  • 空间复杂度:${O(N)}$
  • 执行用时:60ms, 在所有JavaScript提交中击败了99.51%的用户,内存消耗:37.8MB,在所有JavaScript提交中击败了88%的用户

解法3:栈

完全参考官方解答,自己没有这个脑子,因为我是猪脑子

可以把两个链表的比较操作,改为递归过程,就是两个链表头部值较小的一个节点与剩下元素的merge操作结果合并,代码还是挺好理解的:

var mergeTwoLists = function (l1, l2) {
  if (!l1) {
    return l2;
  }

  if (!l2) {
    return l1;
  }

  if (l1.val < l2.val) {
    l1.next = mergeTwoLists(l1.next, l2);
    return l1;
  }

  l2.next = mergeTwoLists(l1.next, l2);
  return l2;
};
  • 时间复杂度:${O(m+n)}$
  • 空间复杂度:${O(m+n)}$
  • 执行用时:92ms, 在所有JavaScript提交中击败了76.44%的用户,内存消耗39.5MB,在所有JavaScript提交中击败了33.39%的用户
以下是递归实现两两交换链表节点的C语言代码: ```c #include <stdio.h> #include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* swapPairs(struct ListNode* head) { if (head == NULL || head->next == NULL) { return head; } struct ListNode *newHead = head->next; head->next = swapPairs(newHead->next); newHead->next = head; return newHead; } int main() { struct ListNode *node1 = (struct ListNode*)malloc(sizeof(struct ListNode)); struct ListNode *node2 = (struct ListNode*)malloc(sizeof(struct ListNode)); struct ListNode *node3 = (struct ListNode*)malloc(sizeof(struct ListNode)); struct ListNode *node4 = (struct ListNode*)malloc(sizeof(struct ListNode)); node1->val = 1; node2->val = 2; node3->val = 3; node4->val = 4; node1->next = node2; node2->next = node3; node3->next = node4; node4->next = NULL; struct ListNode *newHead = swapPairs(node1); while (newHead != NULL) { printf("%d ", newHead->val); newHead = newHead->next; } return 0; } ``` 以上代码,我们定义了一个结构体 `ListNode` 表示链表节点,包含一个整型变量 `val` 和一个指向下一个节点的指针 `next`。函数 `swapPairs` 是递归实现两两交换链表节点的函数,它的参数是链表节点指针 `head`,返回值是交换后的链表节点指针。如果链表为空或者只有一个节点,直接返回该节点;否则,交换前两个节点,并递归处理剩下的节点。最后返回新的链表节点指针。 在 `main` 函数,我们创建了一个包含四个节点链表,并调用 `swapPairs` 函数对链表进行两两交换。最后输出交换后的链表节点值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值