• “反转链表”相关的题目


    反转链表的题型总结一下无外乎就这几种:

      1.从头到尾反转链表

      2.反转链表的前n个节点

      3.反转链表的m到n个节点

      4.反转链表从a节点到b节点左闭右开区间节点

      5.k个一组反转链表

    1.从头到尾反转链表

      从头到尾反转链表是最基本的反转链表题目,无论是迭代法还是递归法都是非常基础和简单的,但是也是考察的重点,我参考了其他大佬的模板,将这两种整合一下,如下:

      (1)迭代法:

    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)递归法

    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.反转链表的前n个节点

      虽然没有直接的这种题型,但其实反转从m到n个节点是跟这个有关系的

      反转前n个节点其实和反转全部节点是一样的,在判断的时候,全部反转的条件是pCur != nullptr,而反转前n个的话可以找到第n+1个节点end,判断条件改成pCur != end,然后把原来的头结点head接到第n+1个节点end上就行了。

      (1)迭代法:

    // 反转链表的前n个节点,返回新的头结点
        ListNode* reverseN(ListNode*head, int n) {
            ListNode* successor = head;
            for (int i = 0; i < n; i++) {
                if (successor == nullptr) {
                    return head;
                }
                successor = successor->next;
            }
            ListNode* pPre = nullptr;
            ListNode* pCur = head;
            ListNode* pNext = nullptr;
            while(pCur != successor)
            {
                pNext = pCur->next;
                pCur->next = pPre;
                pPre = pCur;
                pCur = pNext;
            }
            head->next = successor;
            return pPre;
        }

      (2)递归法:

        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;
        }

    3.反转链表的m到n个节点

      (1)迭代法:

      迭代法的思路就是找到第m个节点,记录第m-1个节点,一趟遍历完成反转

    class Solution {
    public:
        ListNode* reverseBetween(ListNode* head, int m, int n) {
            ListNode* pCur = head;
            ListNode* pPre = nullptr;
            ListNode* pNext = nullptr;
            ListNode* pPreBegin = nullptr; // m-1个节点
            ListNode* pBegin = nullptr; // 第m个节点
            for(int i=0;i<m-1;i++)
            {
                pPreBegin = pCur;
                pCur = pCur->next;
            }
            pBegin = pCur;
            for(int j=m;j<=n;j++)
            {
                pNext = pCur->next;
                pCur->next = pPre;
                pPre = pCur;
                pCur = pNext;
            }
            if(m != 1)
            {
                pPreBegin->next = pPre;
            }
            pBegin->next = pNext;
            return m==1? pPre : head;
        }
    };

      (2)递归法:

      这个题型跟反转前n个节点紧密相关,以为当m=1时,就是反转前n个节点,所以如下,其中的reverseN函数就是第二种题型里的函数,迭代和递归两个都可以:

    ListNode* reverseBetween(ListNode* head, int m, int n) {
            if (m == 1) {
                return reverseN(head, n);
            }
            head->next = reverseBetween(head->next, m-1, n-1);
            return head;
        }

     4.反转链表从a节点(假设a为头节点)到b节点左闭右开区间节点

      反转所有节点的思路是,反转从a节点到nullptr节点的所有节点;而这个题型跟反转所有节点其实是一样的,变成了反转从a到b的节点,左闭右开,只需要改一下条件就行

    ListNode* reverseList(ListNode* a, ListNode b) {
            ListNode* pPre = nullptr;
            ListNode* pCur = head;
            ListNode* pNext = nullptr;
            while(pCur != b)
            {
                pNext = pCur->next;
                pCur->next = pPre;
                pPre = pCur;
                pCur = pNext;
            }
            return pPre;
        }
    

    5.k个一组反转链表

    先反转前k个,再递归反转后面的,当然要注意如果不满足k个就不反转了,这个题跟第4种情况紧密相关

    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 = reverseListNode(a, b); // 先反转前k个元素
            a->next = reverseKGroup(b, k); // 再递归反转后面的
            return newHead;
        }
    private:
        ListNode* reverseListNode(ListNode* a, ListNode* b) { //实现一个函数,翻转从a到b的部分
                ListNode* pCur = a;
                ListNode* pNext = nullptr;
                ListNode* pPre = nullptr;
                while (pCur != b) {
                    pNext = pCur->next;
                    pCur->next = pPre;
                    pPre = pCur;
                    pCur = pNext;
                }
                return pPre; // 返回新的头
        }    
    };
  • 相关阅读:
    euler v10 dracut失败
    基于RYU应用开发之负载均衡
    4、网上收集Storm 讲解图
    3、SpringBoot 集成Storm wordcount
    git常用
    3、SpringBoot集成Storm WorldCount
    2、Storm中的一些概念理解
    1、Storm集群安装
    8、Spring-Kafka Recving Messages
    7、Kafka、AMQ、RabbitMQ对比
  • 原文地址:https://www.cnblogs.com/masbay/p/14044877.html
Copyright © 2020-2023  润新知