菜鸟笔记
提升您的技术认知

【C++】“反转链表”相关的题目

1.反转链表:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

(1)这道题是经典的题目了,用迭代的方式解决也是很容易的,代码量也不大。分享一个我个人做题的方式,我会先在题目开头写注释,理清我结题的思路,然后写代码就很容易了。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //首先需要判断特殊情况
        //需要三个指针实现,先记录当前节点的下一个节点,然后把当前节点的后继节点变成前一个节点,然后把当前节点变成前一个节点,然后把下一个节点变成当前节点往后循环,最后要注意链表的头结点边到最后了
        //开始撸
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* pPre = nullptr;
        ListNode* pCur = head;
        ListNode* pNext = nullptr;
        while(pCur != nullptr)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }return pPre;

    }
};

(2)递归解法:简直是优雅

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //使用递归的方式进行反转,递归反转链表代码太简洁和优雅了,但是要注意基线条件,不能无限循环,使用递归的核心:不要跳到递归里去!
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* last = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return last;
    }
};

2.反转链表II:

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

(1)递归,空间换时间,我佛了。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        //按照题意,时间复杂度为O(n)
        //可以使用迭代和递归两种方式进行,时间复杂度都是O(n),但是递归的空间复杂度为O(n),而迭代为O(1)
        
        //递归解法
        if(m == 1)
            return reverseN(head, n);
        head->next = reverseBetween(head->next, m-1, n-1);
        return head;  
    }
    ListNode* successor = nullptr;
    ListNode* reverseN(ListNode* head, int n)
    {
        if(n==1)
        {
            successor = head->next;
            return head;
        }
        ListNode* last = reverseN(head->next, n-1);
        head->next->next = head;
        head->next = successor;
        return last;
    }

(2)迭代实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        //按照题意,时间复杂度为O(n)
        //可以使用迭代和递归两种方式进行,时间复杂度都是O(n),但是递归的空间复杂度为O(n),而迭代为O(1)
        
        //迭代解法
        ListNode* pCur = head;
        ListNode* pPre = nullptr;
        ListNode* pNext = nullptr;
        ListNode* pPreM = nullptr;
        ListNode* pM = nullptr;
        for(int i=0;i<m-1;i++)
        {
            pPreM = pCur;
            pCur = pCur->next;
        }
        pM = pCur;
        for(int j=m;j<=n;j++)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }
        if(m != 1)
        {
            pPreM->next = pPre;
        }
        pM->next = pNext;
        return m==1? pPre : head;
    }

};

 3.K个一组反转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

/**
 * 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* reverseKGroup(ListNode* head, int k) {
        //先反转以head开头的k个元素
        //将第k+1个元素作为head递归调用reverseKGroup函数
        //将上述两个过程的结果连接起来
        //base case 如果最后的元素不足k个,就保持不变
        if(head == nullptr)
            return nullptr;
        ListNode* a = head;
        ListNode* b = head;
        for(int i=0;i<k;i++)
        {
            if(b == nullptr)
                return head;
            b = b->next;
        }
        ListNode* newHead = reverse(a,b);
        a->next = reverseKGroup(b,k);
        return newHead;
    }
    ListNode* reverse(ListNode* a, ListNode* b)
    {
        ListNode* pCur = a;
        ListNode* pPre = nullptr;
        ListNode* pNext = nullptr;
        while(pCur != b)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }
        return pPre;

    }
};