(刷题学习)C++从翻转链表到k个一组翻转链表

  • Post author:
  • Post category:其他


刷题不是为了刷题,而是为了锻炼解题思路,因为题是刷不完的,但是解题思路又是在一定题量的基础上积累提炼的,所以现在就来看看其中的一个升华过程: 从

翻转链表



k个一组翻转链表

题目与判题环境:《

power by leetcode

》,感谢leetcode平台和上面的大佬们。

开始:


206. 反转链表 – 力扣(LeetCode)

链表大伙都很熟悉了,一个结构体的事情(原理和实现不提),现在有这么个链表和一个需求如下:

将这个链表进行翻转,就是将链表的头变成尾,尾变成头,中间元素也一样进行翻转;

对于数组而言,这个很容易进行翻转,首尾两个指针,逐步向中间逼近的同时翻转即可。

但是链表只给你一个头指针,后面有啥,你并不知道,并且内存空间不连续,你只有遍历了一次,才知道链表的全貌。


翻转链表代码很简单,最主要是如何理解思路;


  • prelude

    序曲,曲奏,序幕 所以你可以看到很多大佬们的代码里面有pre的,这就是prelude的简写。


  • cursor

    游标,如果学过数据库之类的,相信都不陌生,大佬们都简写为 cur

这里只使用

迭代/双指针法

进行翻转,想要学习递归之类的,请转去相应题目看题解。


先创建个nullptr节点,然后让头节点指向它,然后像经典的swap函数一样做法,遍历一遍即可,最后返回pre节点。

(会动的)

相应代码:

/**
 * 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* reverseList(ListNode* head) {
        ListNode* pre = nullptr ;
        ListNode* cur = head ;
        while(cur){
            ListNode* next = cur->next;         //只是为了暂时保存下个节点的信息
            cur -> next = pre ;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

很好,然后通过这道题目,可以有变形的k个一组翻转链表;


25. K 个一组翻转链表 – 力扣(LeetCode)

题目会给一个头节点,一个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) {
        ListNode* roll = new ListNode(0);//创建虚拟节点
        roll -> next = head;//虚拟节点的下一个节点为头节点
        ListNode *start = roll ;
        ListNode *end = roll ;
​
        while(1){
            //遍历循环探链表真相
            //----------------------------------
            for(int i=0;i<k&&end;i++)end=end->next;//遍历k个节点
            //----------------------------------
            
            //指针为空即退出循环
            //----------------------------------
            if(!end)break;//end指针遍历null即退出循环
            //----------------------------------
            
            //新建节点保节点信息
            //----------------------------------
            ListNode* startNext = start->next;//创建两个节点来保存原有的两个关键节点信息,不让二者在翻转子链表的过程中收到影响;
            ListNode* endNext = end->next;
           //-----------------------------------
            
            //断开链表求单独翻转
            //-----------------------------------
            end -> next = nullptr;      //断开链表,指向nullptr
            start -> next = reverseList(start->next);//调用刚刚写的翻转链表的函数,进行切割好的子链表的翻转操作;
           //-----------------------------------
            
            //链表翻转后有所指向
            //-----------------------------------
            startNext -> next = endNext;//通过翻转前保存的关键节点的信息进行拼接
            //-----------------------------------
            
            //重新定位预备下次操作
            //----------------------------------
            start = end = startNext;//进行定位
            //----------------------------------
        }
        return roll->next;      //返回翻转后的头节点,就是虚拟节点的下一个节点
    }
​
    ListNode* reverseList(ListNode* head){      //翻转链表操作,返回头节点 pre
        ListNode* pre = nullptr;
        ListNode* cur = head;      
        while(cur){
            ListNode* next = cur->next;
            cur -> next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

好了,到这里你就会了两道题,然后可以触类旁通、举一反三。不管链表题怎么变,

都不会做

。呃,都有点思路。

参考链接:


  1. 206. 反转链表 – 力扣(LeetCode)


  2. 25. K 个一组翻转链表 – 力扣(LeetCode)


  3. LeetCode 每日一题25. K 个一组翻转链表 | 手写图解版思路 + 代码讲解

  4. 相关题解



版权声明:本文为weixin_51334923原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。