【算法day21】K 个一组翻转链表——给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍

25. K 个一组翻转链表

https://leetcode.cn/problems/reverse-nodes-in-k-group/description/

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

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

二:进行优化:

1.优化掉链表内部的倒置逻辑,不用循环,改成用迭代
2.优化掉pair数据的传递,改成用tie
3.简化逻辑,减少冗余的变量

在这里插入图片描述

/**
 * 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:
    pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail, int k) {
        // 把K个链表倒置
        ListNode* cur=head,*pre=nullptr;
        tail->next = nullptr;
        while(cur){
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur =next;    
        }
        // 现在的tail就是新的head了
        return {tail, head};
    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(k==1) return head;
        int cur_node_num = 0;
        ListNode *p = head, *tmp_tail, *new_head, *tmp_head = head,
                 *old_tail = nullptr;
        // p用来遍历节点
        // tmp_tail用来记录当前尾巴
        // new_head 记录下一个头
        // tmp_head 记录当前头  tmp_head到tmp_tail是K个节点
        // ans记录所有的头
        ListNode* ans = nullptr;
        while (p) {
            cur_node_num += 1;
            if (cur_node_num % k == 0) {
                // 找到了五个连续的节点
                new_head = p->next;
                //
                tie(tmp_head,tmp_tail) = reverseK(tmp_head, p, k);
                if (!old_tail) {
                    // 第一组转置,会更新掉头节点
                    ans = tmp_head;
                } else {
                    old_tail->next = tmp_head;
                }
                old_tail = tmp_tail;
                tmp_tail->next = new_head;

                // 完成修改后
                p = old_tail->next;
                tmp_head = p;
            } else {
                p = p->next;
            }
        }

        if (cur_node_num % k != 0) {
            // 剩下的按原有顺序
            old_tail->next = tmp_head;
        }
        return ans;
    }
};

一:暴力解法

在这里插入图片描述

/**
 * 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:
    pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail, int k) {
        // 把K个链表倒置
        ListNode* ans = tail;
        tail->next = nullptr;
        for (int i = 0; i < k - 1; i++) {
            ListNode *p = head, *pre;
            while (p && p->next) {
                pre = p;
                p = p->next;
            }
            // 每次都找到最后一个节点,挂到tail上面
            tail->next = p;
            tail = tail->next;
            // 要从原来的链上删除掉这个节点
            pre->next = nullptr;
        }
        tail->next = head;
        tail = tail->next;
        // 现在的tail就是新的head了
        return {ans, tail};
    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        int cur_node_num = 0;
        ListNode *p = head, *tmp_tail, *new_head, *tmp_head = head,
                 *old_tail = nullptr;
        // p用来遍历节点
        // tmp_tail用来记录当前尾巴
        // new_head 记录下一个头
        // tmp_head 记录当前头  tmp_head到tmp_tail是K个节点
        // ans记录所有的头
        ListNode* ans = nullptr;
        while (p) {
            cur_node_num += 1;
            if (cur_node_num % k == 0) {
                // 找到了五个连续的节点
                tmp_tail = p;
                new_head = p->next;
                //
                pair<ListNode*, ListNode*> t = reverseK(tmp_head, tmp_tail, k);
                ListNode *f_h = t.first, *f_t = t.second;
                if (!old_tail) {
                    // 第一组转置,会更新掉头节点
                    ans = f_h;
                } else {
                    old_tail->next = f_h;
                }
                old_tail = f_t;
                f_t->next = new_head;

                // 完成修改后
                p = old_tail->next;
                tmp_head = p;
            } else {
                p = p->next;
            }
        }

        if (cur_node_num % k != 0) {
            // 剩下的按原有顺序
            old_tail->next = tmp_head;
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值