1-4 LC206 反转链表 LC92 反转链表II C++ Java力扣刷题笔记

LC206 反转链表

在这里插入图片描述

LC206

1.读题

反转一个单链表。
在这里插入图片描述

2.题解

【1】解题思路

这里参考王尼玛大佬的题解(这IDemmmm

这个图解超级清晰啊!
感谢大佬!!

方法一 迭代

这里我们用双指针迭代法!
【1】我们要定义两个指针pre——初始指向nullptr & cur——初始指向head
在这里插入图片描述

【2】每次让cuinext 指向pre ——这样就实现了一次局部反转!
在这里插入图片描述
【3】每次迭代到cur 就重复【2】操作
然后pre cur两个指针都前进一位
在这里插入图片描述
【4】迭代完成之后 pre变为最后一个节点
在这里插入图片描述
以上四步走省略了一个变量 cur_next

此变量将会将cur的下一个节点保存起来!!

我们在代码中会看到这个变量发挥的作用滴~

方法二 递归

简要来说

一次拆掉一个节点并递归处理剩余的子链表

递归法不是很好理解
So——
二刷见

这个坑放在这里!一定要回来填呐!

【2】代码逻辑

方法一 迭代

【1】初始化定义两个指针 一个指向空——pre 一个指向头节点——cur
在这里插入图片描述

【2】只要cur不为空 就一直循环
【3】循环中不断地让cur指向pre
在这里插入图片描述

【3’】并不断将二者前移

在这里插入图片描述

方法二 递归

二刷见

3.C++代码

方法一 迭代

超棒的逻辑性!

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = nullptr;//定义指针pre
        ListNode* cur = head;//定义指针cur

        while(cur) {
            ListNode* cur_next = cur -> next;//创建一个cur_next变量存储cur指针的下一个节点
            cur -> next = pre;//cur的next指向pre
            pre = cur;//pre往前进一位
            cur = cur_next;//cur往前进一位

        }
        return pre;
    }
};

在这里插入图片描述

4.Java代码

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode cur_next = null;

        while(cur != null) {
            cur_next = cur.next;
            cur.next = pre;
            pre = cur;//pre前移!
            cur = cur_next;//cur前移!
        }
        return pre;
    }
}

在这里插入图片描述

LC92 反转链表II

LC92

1.读题

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

在这里插入图片描述

2.题解

这里挖的坑是 使用头插法一次遍历反转链表!
坐等二刷什么滴

【1】解题思路

参考了LC 木已成舟 大佬的解析
https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/java-shuang-zhi-zhen-tou-cha-fa-by-mu-yi-cheng-zho/
【0】使用虚拟头节点 避免复杂的分类讨论
【1】先定义两个指针 (和LC206一样 )g(guard守卫) & p(point)

【2】根据 m 确定g p的位置 —— 将g动到第一个要反转的节点前面 将p移动到第一个要反转的节点的位置上
下面的图解中 以 n=2 m=4 为例
在这里插入图片描述
【3】把p后面的元素删除 然后添加到g的后面——“头插法”
在这里插入图片描述
【4】根据mn重复步骤 【2】
在这里插入图片描述
【5】返回虚拟头节点指向的内容(即为反转好的链表)

【2】代码逻辑

【1】定义虚拟头节点
在这里插入图片描述
【2】初始化指针
(根据虚拟头节点)
在这里插入图片描述
【3】让g达到第一个要反转的节点前面
让p达到第一个要反转的节点位置
这是本题的核心思想!!!!
肥肠重要!!
在这里插入图片描述
在这里插入图片描述

【4】头插法插入节点 达到反转的效果
在这里插入图片描述
这一步的操作关键是删除p后面的元素然后添加到g的后面
在这里插入图片描述
【5】最后输出虚拟头节点指向的链表即可
在这里插入图片描述

3.C++代码

与JAVA版本的几乎一致哦~
二刷仔细多看几遍 ~

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        int pos = 1;
        ListNode* dummyNode = new ListNode(0);
        dummyNode->next = head;
        ListNode* pre = dummyNode;
        ListNode* cur = head;

        while(cur && pos < left) {
            pre = pre -> next;
            cur = cur -> next;
            pos ++;
        }
        ListNode* tailNode = cur;
        while(cur && pos <= right) {
            ListNode* removed = cur -> next;
            cur -> next = pre -> next;
            pre -> next = cur;
            tailNode->next = removed;
            cur = removed;
            pos ++;
        }
        return dummyNode->next;
    }
};

在这里插入图片描述

4.Java代码

详细得就离谱!
看不懂你来找我!!
(结合着上面的图)

class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode dummyNode = new ListNode(0);
        //因为头节点可能会发生变化 所以使用虚拟头节点可以避免复杂的分类讨论
        dummyNode.next = head;//虚拟头节点指向头节点

        ListNode g = dummyNode;
        ListNode p = dummyNode.next;//初始化两个指针(LC206中熟悉的操作鸭)

        for (int step = 0; step < m - 1; step++) {
            //第一步 
            //g从虚拟头节点走m-1步 来到m节点的前一个节点————即第一个要反转的节点的前面
            //p从虚拟头节点的下一个位置走m-1步 来到m节点
            g = g.next;
            p = p.next;
        }

        //第二步
        //头插法插入节点
        for (int i = 0; i < n-m; i++){
            //【1】定义删除p后面的节点 为 removed
            ListNode removed = p.next;
            //【2】p指向删除掉元素的下一个节点
            p.next = p.next.next;

            //【3】删除节点指向p节点(也就是g.next)
            removed.next = g.next;
            //【4】最后一步 将g与删除节点连接起来
            g.next = removed;
        }
        
        return dummyNode.next;
    }
}

在这里插入图片描述

5.本题收获

1.链表中通过步长做标准——访问到特定的那个节点
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值