【icyle】Leetcode-cn:24. 两两交换链表中的节点

题目

解答1:递归

思路

分类讨论:

  1. 如果链表中至少有两个节点:
    原始链表的头节点变成新的链表的第二个结点
    原始链表的第二个节点变成新的链表的头结点
    本组第一个结点应该接上下一组的第二个结点,所以用递归找到下一组
  2. 链表中没有节点,或者链表中只有一个节点:结束递归。
代码
/*
 * @lc app=leetcode.cn id=24 lang=cpp
 *
 * [24] 两两交换链表中的节点
 */

// @lc code=start
/**
 * 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)
    {
        //链表没有结点或者只有一个结点
        if (head == nullptr || head->next == nullptr)
        {
            return head;
        }

        //以1和2、3和4这样两两分组
        //定义第二个结点作为newHead
        ListNode *newHead = head->next;

        //递归,完成后面组的交换
        head->next = swapPairs(newHead->next);

        //2后面接上1,完成第一组的交换
        newHead->next = head;
        return newHead;
    }
};

// @lc code=end
时间复杂度和空间复杂度
  • 时间复杂度: O(n) 。其中 n 是链表的节点数量。由于成组递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,每次对组内两个结点进行操作,渐进时间复杂度即为 O(n)
  • 空间复杂度:O(n) 。其中 n 是链表的节点数量。由于成组递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,所需栈空间渐进时间复杂度也是 O(n)

解答2:迭代

思路

定义dummy,通过某一组和该组前面一个结点,对该组的两个结点进行交换。交换操作是一定需要掌握的基础,此处不再赘述。

代码
/*
 * @lc app=leetcode.cn id=24 lang=cpp
 *
 * [24] 两两交换链表中的节点
 */

// @lc code=start
/**
 * 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) {}
 * };
 */

using namespace std;
class Solution
{
public:
    ListNode *swapPairs(ListNode *head)
    {
        //定义一个头指针指向头结点
        ListNode *preHead = new ListNode();
        preHead->next = head;

        //定义中间结点
        ListNode *temp = preHead;

        //还是以1和2、3和4这样两两分组
        //后两个结点均不是空
        while (temp->next != nullptr && temp->next->next != nullptr)
        {
            //p是该组第一个结点,q是该组第二个结点
            ListNode *p = temp->next;
            ListNode *q = temp->next->next;
            //temp指向该组第二个结点
            temp->next = q;

            //p(第一个结点)的下一个结点应该是q的下一个结点(也就是第二组的第一个结点,不要破坏下一组的结构)
            p->next = q->next;
            //q(第二个结点)的下一个结点就是他前面的结点p
            q->next = p;
            //p(第一个结点)此时已经换成第二个结点,此时temp指向p,那么temp->next就可以指向下一组结点
            temp = p;
        }

        //返回一开始的头结点即可
        return preHead->next;
    }
};
// @lc code=end

时间复杂度和空间复杂度(官方答案,说的很好)
  • 时间复杂度: O(n) 。其中 n 是链表的节点数量。由于成组递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,每次对组内两个结点进行操作,渐进时间复杂度即为 O(n)
  • 空间复杂度:O(1)

反思与总结

递归和迭代使用的又一经典例题。

你可能感兴趣的:(c++,leetcode,算法)