算法设计与分析 第十二周 k个一组翻转链表


1 题目描述

在这里插入图片描述


2 选题原因

讲道理这个周确实没讲啥东西…秉承着随机的原则,在首页闭着眼睛点了一下鼠标,选中了这道题。


3 题目分析及算法

3.1 常规分析

分析这道题目,其实是比较简单的。涉及的操作无非就是节点的转移,思考清楚就没有太大的难度。
看这道题,说白了就是将不同段的节点颠倒过来,其实实现起来很简单。我们先看一段链表的倒置

在这里插入图片描述

当我们要倒置的时候,应该是从头节点开始,依次将头节点放在最后。例如上图,我们从1开始,先使用一个指针指向2,接着将1节点放在队列的最后(该节点下一个节点稍后会说),接着,将头节点更新为指针指向的节点(即节点2)。

算法如下:
FOR i = 1: k
temp = head -> next;
head -> next = tail;
tail = head;
ENDFOR

3.2 问题所在

接下来,我们要考虑的问题是:先调换前面的组还是先调换后面的组。
仔细观察一下。当前组的首节点会被放在最后,和下一个组的首节点相接,而下一组的首节点是什么?取决于我们的调换顺序。如果我们从前往后调换,那么这一组会在下一组首节点被放在最后之前连接上!而如果我们从后往前调换,就会在下一组调换完成连接上节点,也正是正常顺序!


4 关键代码

4.1 组内节点调换

            //反转节点
            while (count > 0) {
                //next 下一个头节点
                //next_head 下一个要放在最后的节点
                ListNode* next = head->next;
                head->next = next_head;
                next_head = head;
                head = next;
                count--;
            }

4.2 递归的从后向前调换

        while (next_head != NULL && count != k) {
            next_head = next_head->next;
            count++;
        }
        //递归后面的组先反转,用反转后新的头作为自己尾节点的下一个节点
        if (count == k) {
            next_head = reverseKGroup(next_head, k);
        }

5 运行结果

在这里插入图片描述


6 源代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* next_head = head;                 //标记下一组要反转的位置
        int count = 0;                              //标记当前组的节点数
        //找到下一组节点
        while (next_head != NULL && count != k) {
            next_head = next_head->next;
            count++;
        }
        //递归后面的组先反转,用反转后新的头作为自己尾节点的下一个节点
        if (count == k) {
            next_head = reverseKGroup(next_head, k);

            //反转节点
            while (count > 0) {
                //next 下一个头节点
                //next_head 下一个要放在最后的节点
                ListNode* next = head->next;
                head->next = next_head;
                next_head = head;
                head = next;
                count--;
            }
            //指向新的头
            head = next_head;
        }
        return head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值