Leetcode 206.反转链表

前言

坚持刷题是一种信念,在找工作强调算法能力的今天,刷题已经成为了我们生活的一部分,无论是为了谋一份工作还是参加算法比赛,我们都需要刷题;这篇文章主要包括了博主对于 链接: Leetcode 206.反转链表 的一些理解以及解答方式,希望能帮到你。


以下是博主对于题目的分析以及解决方法,仅供参考

一、题目描述与分析

题目链接在前言里面提供了,感兴趣的同学可以进去看看。
这个题目是一个经典的链表问题,要求反转一个单链表。这道问题考察了对链表数据结构的理解以及对链表操作的掌握。
这道题是链表操作的基础问题,也是面试中常见的问题之一。解决这个问题需要对链表的节点操作有一定的了解,同时也需要掌握链表的遍历和指针操作技巧。学习和掌握这道题可以帮助加深对链表数据结构的理解,并为解决更复杂的链表问题打下基础。

二、题解以及代码

这里是博主对于题目的分析以及解决方法
这里我提供了三种不同的方法来实现链表的反转:
1、迭代法
思路: 迭代法是通过遍历链表,逐步改变每个节点的指针方向,使其指向前一个节点,从而实现链表的反转。
1)初始化 prevnull,表示反转后的链表头节点是 null
2)初始化 current 为输入链表的头节点 head
3)进入循环,遍历链表直到 current 变为 null
4)在循环内部,首先暂存 current 的下一个节点为 nextTemp
5)然后将 currentnext 指针指向 prev,这一步实现了反转。
6)更新 prevcurrent,更新 currentnextTemp,以便下一次迭代。
7)当循环结束后,prev 指向反转后的链表的头节点,返回 prev 作为结果。
复杂度分析:
时间复杂度: O(n),需要遍历整个链表一次。
空间复杂度: O(1),只需要常数级别的额外空间来存储指针。

public ListNode reverseList(ListNode head) {
    ListNode prev = null; // 前一个节点初始化为null
    ListNode current = head; // 当前节点初始化为链表的头节点

    while (current != null) {
        ListNode nextTemp = current.next; // 暂存当前节点的下一个节点
        current.next = prev; // 将当前节点的指针指向前一个节点,实现反转
        prev = current; // 更新前一个节点为当前节点
        current = nextTemp; // 更新当前节点为下一个节点
    }

    return prev; // 最终prev指向新的链表头,返回新链表的头节点
}

2、递归方法
思路:递归法是通过递归调用来实现链表反转,递归的核心思想是将问题拆分为更小的子问题,然后递归地解决这些子问题。
1)如果输入链表为空或只有一个节点,直接返回 head,不需要进行反转。
2)递归调用 reverseList 函数,传入 head.next,以便反转后面的链表,将返回结果保存在 newHead 中。
3)将 head.next.next 指向 head,这一步实现了当前节点的反转。
4)将 head.next 指向 null,防止形成环。
5)返回 newHead 作为结果,它是反转后的链表的头节点。
复杂度分析:
时间复杂度: O(n),需要递归调用 n 次,每次操作的时间复杂度是常数级别的。
空间复杂度: O(n),递归调用的栈深度为 n,因此空间复杂度是 O(n)。

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head; // 如果链表为空或只有一个节点,直接返回该节点
    }

    ListNode newHead = reverseList(head.next); // 递归调用反转后面的链表
    head.next.next = head; // 将当前节点的下一个节点的指针指向当前节点,实现反转
    head.next = null; // 将当前节点的指针指向null,防止形成环

    return newHead; // 返回新的链表头
}

3、使用栈
思路: 使用栈数据结构来反转链表。首先,将链表的所有节点依次压入栈中,然后从栈中弹出节点,构建一个新的链表,这个新链表就是反转后的链表。
1)如果输入链表为空,直接返回 null
2)创建一个栈 stack,用于存储链表的节点。
3)遍历输入链表,将每个节点依次压入栈 stack 中。
4)弹出栈顶节点,将其作为新链表的头节点,保存在 newHead 中。
5)初始化一个指针 current,指向 newHead,用于构建反转后的链表。
6)依次弹出栈中的节点,将其设为 current 的下一个节点,构建反转后的链表。
7)将最后一个节点的 next 指针设置为 null,以防止形成环。
8)返回 newHead 作为结果,它是反转后的链表的头节点。
复杂度分析:
时间复杂度: O(n),需要遍历链表两次,一次将节点入栈,一次将节点出栈。
空间复杂度: O(n),需要额外的栈空间来存储节点。

public ListNode reverseList(ListNode head) {
    if (head == null) {
        return null;
    }

    Stack<ListNode> stack = new Stack<>(); // 使用栈来暂存链表节点

    // 将链表节点依次入栈
    while (head != null) {
        stack.push(head);
        head = head.next;
    }

    ListNode newHead = stack.pop(); // 弹出栈顶节点作为新链表的头节点
    ListNode current = newHead;

    // 依次弹出栈中的节点,构建反转后的链表
    while (!stack.isEmpty()) {
        current.next = stack.pop();
        current = current.next;
    }
    current.next = null; // 最后一个节点的next设置为null,防止形成环

    return newHead; // 返回新的链表头
}

总结

写题目时的一些想法以及收获
在写这个题目时看见题目就立马想到了迭代法,这个方法是一个非常经典的解决链表反转的方法,在用第二个方法时遇见了一些困难,递归本身就比较难以理解,用栈来解决这个题目也算是比较好理解。
那么今天这篇文章就到此为止了,希望可以帮到你,如果有什么问题可以私聊或者在评论区提出,博主看见了就会回复。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值