leetcode.25:k个一组翻转链表

给定一个链表,按每k个节点一组翻转链表。需要处理各种边界条件,如k的大小、链表长度不是k的整数倍。解题策略包括模拟翻转链表段并正确连接它们,同时使用额外空间限制为常数。常见难点包括处理翻转链表段、初始化和更新指针以及处理非整数倍长度的情况。
摘要由CSDN通过智能技术生成

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

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

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

示例:

给你这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明:

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
通过次数82,171提交次数132,846

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:
这道题解法很多,但总体的思路是模拟,将链表分为长度为k的链表段,分别翻转每个段内的各个元素,之后将新的头尾正确的链接起来即可。难点在于,本题需要考虑的边界条件比较多,思路容易混乱,容易导致最后的链表链接出错。难点和易混淆点主要有以下几个:
1. 设计翻转k为长度的链表,传入需要翻转的链表的起始节点,返回翻转之后的起始节点。这里和翻转单链表没有太大差别;
2. 与1相对应的,传入的起始节点需要正确的传入,计数为k,如果尾指针初始在头结点的位置,那么向后移动k个位置之后,尾指针的位置向后多移动了一位,因此,每次在移动尾指针之前,需要将尾指针初始化到pre节点。
3. 每次翻转链表之后返回的头尾指针是新的头尾指针,他们的next指向已经不能使用,并且需要给他们指定正确的指向。这就需要保存一个pre指针,和一个next指针,分别指向前驱结点和后继节点;
4. 可以使用dummy节点,好处有两方面,一个是可以记录头结点的位置以便返回,另一个是可以设置为起始位置的pre节点,减少边界条件的判断。

/**
 * 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) {
        if(k<2)return head;
        ListNode *dummy = new ListNode(-1);
        dummy->next = head;
        //ListNode* tail = head;
        ListNode* pre = dummy;

        while(head)
        {
            ListNode* tail = pre;
            int count = k;
            while(count!=0&&tail!=nullptr)
            {
                tail = tail->next;
                count--;
            }
            
            if(tail==nullptr)
            {
                //pre->next = head;
                return dummy->next;
            }
            ListNode* next = tail->next;
            tie(head,tail)= helper(head,tail);
            pre->next = head;
            tail->next = next;

            //cout<<"head:"<<nodePair.first->val<<"\t"<<"tail:"<<nodePair.second->val<<endl;
            //cout<<"head->next:"<<nodePair.first->next->val<<"\t"<<"tail:"<<nodePair.second->val<<endl;
            //head = next;
            pre = tail;
            head = tail->next;


        }
        return dummy->next;
    }


    pair<ListNode*,ListNode*> helper(ListNode* head,ListNode* tail)
    {
        //cout<<"head:"<<head->val<<"\t"<<"tail:"<<tail->val<<endl;
        ListNode* p = head;
        ListNode* pre = head;
        p = p->next;
        pre->next = nullptr;

        while(p!=tail)
        {
            ListNode* temp = p->next;
            p->next = pre;
            pre = p;
            p = temp;
        }
        p->next = pre;

        return {tail,head};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值