算法通关村第二关——链表反转笔记(青铜挑战)

文章介绍了如何使用直接操作链表和递归两种方法实现链表反转,详细解析了每种方法的步骤,包括定义辅助变量、确定递归终止条件和执行反转操作。代码示例展示了Java实现的链表反转过程。
摘要由CSDN通过智能技术生成

链表反转

三种方案:

  1. 虚拟头结点辅助反转(我觉得太麻烦了)
  2. 直接操作链表实现反转
  3. 递归实现反转(工作中不会使用,不过我这里详细的说明了)

1. 直接操作链表实现反转

首先这是链表

image-20230720093215123

因为反转过来之后,1这边指向null,所以定义一个结点为prev = null,用来记录当前节点的前一个

ListNode prev = null,ListNode cur = head(头节点)

image-20230720093742416

反转第一个结点,将cur.next = prev,那么问题就是怎么移动cur呐?所以还需要定义一个ListNode next = cur.next

保存下一个位置,只需要cur = next,这样就等于移动节点(其实就是cur = cur.next ,只是我们需要改变指针后再移动)

下面就是大概代码:

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            cur.next = prev;
            prev = cur
            cur = next;
            .....
        }
    }
}

image-20230720094059789

这里注意,当cur = null时,5正好就是prev,也就是新链表的头节点,所以,返回的新链表,就是prev

public static ListNode reverseListSimple(ListNode head) {
    ListNode prev = null;
    ListNode cur = head;
    while (cur != null) {
        ListNode next = cur.next;
        cur.next = prev;
        prev = curr;
        cur = next;
    }
    return prev;
}

image-20230720095100183

然后一步步下去,最后,返回return即可

image-20230720095221002

2. 递归

参考学习视频链接:LeetCode:206.反转链表 | 双指针法 | 递归法

其实上面那种方法搞懂了,这一题使用递归就不难了

个人认为递归一定要画图,把图画好才懂得快,画图才会懂得递归三要素

递归三要素

三要素其实就是递归的模板,按照三要素来写递归就是递归的套路。

1、确定递归函数的参数和返回值:确定递归过程中需要处理的参数,明确每次递归的返回值进而确定递归函数的返回类型

2、确定递归终止条件,即函数return的出口:终止条件写的不对,操作系统的内存栈一定会溢出,毕竟递归也是有限制的

3、确定单层递归的逻辑:明确每次递归要进行什么操作

第一步:函数怎么往前递归

链表往前移动就是通过:head = head.next;

返回值是什么?ListNode。

由上面两个就可以得出:ListNode newHead = reverseListByRecurse(head.next);

第二步:确定递归终止条件

这里首先要明白,递归就类似与压栈的形式,出栈的时候再进行移动

image-20230720101111489

我们从这个图可以看出,当public static ListNode reverseListByRecurse(ListNode head)

参数head.next为空的时候,就是终止条件:

注意终止条件记得极限情况,当头节点就是空的时候,那就直接不用递归了

那么代码就是这样:

public static ListNode reverseListByRecurse(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newHead = reverseListByRecurse(head.next);
    .....
    return newHead;
}

这里retuen newHead,之后,就可以开始我们的逻辑

第三步:确定要执行的操作

image-20230720102752060

从图可得出,head.next.next = head;就是操作

这时候由图可得,会发现,head得指针域,head.next还指向3,所以还需要加上,head.next = null

最后的代码如下:

public static ListNode reverseListByRecurse(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newHead = reverseListByRecurse(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值