25. K 个一组翻转链表,206. 反转链表,92. 反转链表 II - leetcode刷题

一、题目

25. K 个一组翻转链表
206. 反转链表
92. 反转链表 II

二、分析

这个看似很难,但是化繁为简之后,一切就“拨开云雾见天日”了,但是写代码仍然要非常细心。

  1. 拆分成子问题:给定一个头尾指针,翻转整个链表,就成了题目中2、3题。
  2. 每隔k步,进行一次上述操作。

三、代码

  1. 25. K 个一组翻转链表
class Solution {
public:
	// 辅助函数,翻转部分链表(给定头尾指针)
    pair<ListNode *, ListNode *> reverseOne(ListNode *head, ListNode *tail){
        tail->next = nullptr;
        ListNode* pleft = head;
        ListNode* pright = head->next;
        while(pright != nullptr){
            ListNode* temp = pright->next;
            pright->next = pleft;
            pleft = pright;
            pright = temp;
        }
        // head->next 还是原来的第二个节点
        return make_pair(pleft,head);
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        if(k <= 1) return head;
        int count(0);
        ListNode * dumpy = new ListNode();
        dumpy->next = head;
        ListNode * p = head;
        ListNode * pfixLeft = dumpy;
        while(p != nullptr){
            count++;
            if(count % k == 0){ //关键操作,建议画图理解一下
                ListNode * temp = p->next;
                pair<ListNode *, ListNode *> res = reverseOne(pfixLeft->next, p);
                pfixLeft->next = res.first;
                pfixLeft = res.second;
                pfixLeft->next = temp;
                p = temp;
                continue;
            }
            p = p->next;
        }
        return dumpy->next;
    }
};

执行用时:16 ms, 在所有 C++ 提交中击败了90.73%的用户
内存消耗:11.2 MB, 在所有 C++ 提交中击败了52.97%的用户

206. 反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head){
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* pleft = head;
        ListNode* pright = head->next;
        while(pright != nullptr){
            ListNode* temp = pright->next;
            pright->next = pleft;
            pleft = pright;
            pright = temp;
        }
        head->next = nullptr;
        return pleft;
    }
};

执行用时:8 ms, 在所有 C++ 提交中击败了68.84%的用户
内存消耗:8.1 MB, 在所有 C++ 提交中击败了53.23%的用户

92. 反转链表 II

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(left == right) return head;
        ListNode *fakerhead = new ListNode();
        ListNode *fakertail = new ListNode();
        fakerhead->next = head;
        ListNode * pright = fakerhead;
        ListNode * pleft = fakerhead;
        int i(0);
        bool flag = false;
        // 找到 pleft 和 pright 
        while(pright != nullptr){
            if(i == left - 1){
                pleft = pright;
            }else if(i == right){
                break;
            }
            pright = pright->next;
            i++;
        }
        // 考虑pright是 tail节点的特殊情况
        if(pright->next == nullptr){
            flag = true;
            pright->next = fakertail;
        } 
        pright = pright->next;

        i = 0;
        //开始真正的翻转部分链表,给定头尾指针(和25题的做法不太一样)
        ListNode * p = pleft->next;
        ListNode * temp = p->next;
        while(i < right - left + 1){
            p->next = pright;
            pright = p;
            if(i == right- left) break;
            p = temp;
            temp = temp->next;
            i++;
        }
        pleft->next = p;
        //仍然是考虑pright是tail节点的情况
        if(flag){
            p = fakerhead->next;
            while(p!= nullptr){
                if(p->next->next == nullptr) p->next = nullptr;
                p = p->next;
            }
        }
        return fakerhead->next;
    }
};

执行用时:16 ms, 在所有 C++ 提交中击败了100%的用户
内存消耗:7.3 MB, 在所有 C++ 提交中击败了32.97%的用户

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值