刷题笔记----每周例题:206. 反转链表.92. 反转链表 II,25. K 个一组翻转链表

206反转链表

206. 反转链表

在这里插入图片描述
题解(递归和迭代):

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //递归
        /*
        //链表节点小于2,返回
        if(head == nullptr || head->next == nullptr)
            return head;
        //递归下一节点链表
        ListNode *p = reverseList(head->next);
        //反转两个节点
        head->next->next = head;
        head->next = nullptr;
        //返回反转后的头节点
        return p;
        */
        //迭代
        ListNode *p = head;
        ListNode *q = new ListNode(0),*tmp = q;
        链表节点小于2,返回
        if(p == nullptr || p->next == nullptr)
            return p;
        else{
            //q为p的下一节点,因为修改了q的指针后,链表就断开了,所以用tmp保存q的下一节点
            q = p->next;
            tmp = q->next;
            //头节点处理
            q->next = p;
            p = q;
            head->next =nullptr;
            //前进
            while(tmp != nullptr){
                q = tmp;
                tmp = tmp->next;
                q->next = p;
                p = q;
            }
            return p;
        }
    }
};

92. 反转链表 II

在这里插入图片描述题解(递归和迭代):
迭代:

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        //迭代
        if(left == right)
            return head;
        else{
            //p1记录left前一个节点,p2记录left节点,tmp记录q的下一节点
            ListNode *p = head;
            ListNode *q = head->next;
            ListNode *tmp = new ListNode(),*p1 = tmp,*p2=tmp;
            p1->next = p;
            int i=1;
            //更新p1p2
            while(i<left){
                p1 = p;
                p = p->next;
                q = p->next;
                ++i;
            }
            p2 = p;
            //处理第一次反转
            int j = right-left;
            if(j>0){
                j--;
                tmp = q->next;
                q->next = p;
            }
            //处理后续反转
            while(j){
                p = q;
                q = tmp;
                tmp = tmp->next;
                j--;
                q->next = p;
            }
            //处理断开处的节点指针
            p2->next = tmp;
            p1->next = q;
            if(left==1)
                return q;
            else 
                return head;
        }
    }
};

递归:

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        //递归1
        if(left == right)
            return head;
        //p1记录left前一个节点,q记录left节点,q1记录q的下一节点
        ListNode *p = new ListNode(),*q = head,*p1 = p,*q1 = p;
        p = head;
        p1->next = p;
        int i = 1;
        while(i<right){
            if(i < left){
                p1 = p;
                p = p->next;
                q = p;                
            }
            else{
                p = p->next;
                q1 = p->next;
            }
            i++;
        }
        p->next = nullptr;
        ListNode *l = reverse(q);
        q->next = q1;
        p1->next = l;
        if(left==1)
            return l;
        else    
            return head;
    }
    //反转链表
    ListNode * reverse(ListNode* head){
        if(head == nullptr||head->next == nullptr)
            return head;
        ListNode *a = reverse(head->next);
        head->next->next = head;
        head->next = nullptr;
        return a;
    }
};
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        //递归2
        if(left == 1)
            return reverse(head,right);
        head->next = reverseBetween(head->next,left-1,right-1);
        return head;
    }
    ListNode *p = new ListNode();
    //反转链表前n个节点
    ListNode* reverse(ListNode* head,int n){
        if(n==1){
            p = head->next;
            return head;
        }
        ListNode *a = reverse(head->next,n-1);
        head->next->next = head;
        head->next = p;
        return a;
    }
};

25. K 个一组翻转链表

在这里插入图片描述

迭代思路:借鉴反转链表的迭代方法,将链表分段,每K个一段,就变成了反转链表的问题,只需稍加变动,需要记住每个反转后的链表的头节点和尾节点,以便于将各个分段链表连接起来。

class Solution {
public:
    ListNode * reversek(ListNode* head, int k){
        ListNode *p = new ListNode(),*q = p,*tmp = p;
            p = head;
            q = head->next;
            tmp = q;
            while(k>1){
                tmp = tmp->next;
                q->next = p;
                if(p == head)
                    p->next = nullptr;
                p = q;
                q = tmp;
                head->next = q;
                k--;
            }
           return p;
        }
    ListNode* reverseKGroup(ListNode* head, int k) { 
        int i=0;
        ListNode *l = head;
        //p11始终指向反转链表的为节点
        ListNode *p11 = new ListNode();
        ListNode *head1 = new ListNode();
        while(l){
        //记录每段链表反转前头节点
            if(i==0)
                head1 = l;
            l = l->next;
            i++;
            //满足条件,准备反转分段链表
            if(i==k){
               i = 0;
               ListNode *tmp = reversek(head1,k);
               if(p11 == nullptr)
                   p11 = head1;
               if(p11 != head1){
                   p11->next = tmp;
                   p11 = head1;
               }
               //第一个分段链表需要特殊处理,改变整个链表的头节点
               if(head1 == head)
                   head = tmp;  
            }
        }
        return head;
    }
};

递归+迭代思路:反转前K个链表用递归解决,然后将各个链表连接起来用迭代

class Solution {
public:
    ListNode *p = new ListNode(),*p1 = p;
    //反转链表前n个节点
    ListNode* reverse(ListNode* head,int n){
        if(n==1){
            p = head->next;
            return head;
        }
        ListNode *a = reverse(head->next,n-1);
        head->next->next = head;
        head->next = p;
        return a;
    }
    ListNode* reverseKGroup(ListNode* head, int k) { 
        int i=0;
        ListNode *l = head;
        //p11始终指向反转链表的为节点
        ListNode *p11 = new ListNode();
        ListNode *head1 = new ListNode();
        while(l){
        //记录每段链表反转前头节点
            if(i==0)
                head1 = l;
            l = l->next;
            i++;
            if(i==k){
            //满足条件,准备反转分段链表
               i = 0;
               ListNode *tmp = reverse(head1,k);
               if(p11 == nullptr)
                   p11 = head1;
               if(p11 != head1){
                   p11->next = tmp;
                   p11 = head1;
               }
               //第一个分段链表需要特殊处理,改变整个链表的头节点
               if(head1 == head)
                   head = tmp;  
            }
        }
        //如果刚好被整分,直接返回修改过的头节点,否则需要将剩下的部分链接到p11(反转链表为指针)上
        return head;
    }
};

纯递归:画图太麻烦,看代码自己想像。

class Solution {
public:
    ListNode *p = new ListNode(),*p1 = p;
    //反转链表前n个节点
    ListNode* reverse(ListNode* head,int n){
        if(n==1){
            //p = head->next;
            return head;
        }
        ListNode *a = reverse(head->next,n-1);
        head->next->next = head;
        //head->next = p;
        return a;
    }
    ListNode* reverseKGroup(ListNode* head, int k) { 
        if(head == nullptr)
            return nullptr;
        ListNode *x = head;
        for(int i=0;i<k;++i){
            if(x==nullptr)
                return head;//最后不足K个节点,直接返回剩下部分的头节点
            x = x->next;//x为低k+1个元素
        }
        //反转前k个节点,h为反转后的头节点,head为反转后的尾节点
        ListNode *h = reverse(head,k);
        //让先反转的尾节点指向下一次反转的头节点
        head->next = reverseKGroup(x,k);
        //返回头节点
        return h;
    }
};


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值