剑指Offer24.反转链表 Python3和Java实现

剑指Offer24.反转链表 Python3和Java实现

个人认为通过栈实现是比较好理解的一种实现方式,但是时间和空间复杂度都比较高,可以用来学习,如果内容有任何错误,欢迎各位大佬指正!

python代码如下:

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # 初始化一个列表(当作栈用)
        stack = []
        # 判断若链表的头结点为空,直接返回该链表
        if head == None:
            return head
        # 遍历链表,将链表中每个节点的值按顺序存入栈stack中(遍历条件为head.next,可以不用从栈中取最后一个元素,hhhh~当然条件为head也是可以的)
        while head.next:
            stack.append(head.val)
            # 不断移动head,使得每次存入栈中的值都是按顺序且向后移动的
            head = head.next
        # 定义一个新链表的头结点为new_head,并指向原链表的最后一个节点(通过上面的遍历此时的head已经是原链表的尾节点了)
        new_head = head
        # 定义一个cur,同样指向原链表的最后一个节点
        cur = new_head
        # 遍历栈,栈不为空就一直弹出最后一个值(注意此时弹出的值,这里栈中如果存的不是值而是节点,会超时,不知道有没有不超时的办法,有的话欢迎留言告诉我!)
        while stack:
            # 这一步相当于弹出最后一个值,并用这个值新创建一个新节点,并通过cur.next,使得new_head与新节点连接起来(new_head的next为新节点)
            cur.next = ListNode(stack.pop())
            # 此时cur在本次遍历中功成身退,完成了将new_head和新节点连接起来的工作后,移动到了新节点处
            cur = cur.next
        # 注意返回的是新链表的头节点,此时的cur已经是新链表的最后一个节点了
        return new_head

Java代码如下:

class Solution {
    public ListNode reverseList(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        // 必须先判空,否则如果输入空的链表下面的遍历会报空指针异常
        if(head == null){
            return head;
        }
        // 和python的区别1是这边可以直接往栈内插入节点,虽然可能效率低一点
        while (head.next != null){
            stack.push(head);
            head = head.next;
        }
        ListNode new_head = head;
        ListNode cur = new_head;
        while (!stack.isEmpty()){
            cur.next = stack.pop();
            cur = cur.next;
        }
        // 和python的区别2是最后必须让尾节点的next指向null,否则会形成环
        cur.next = null;
        return new_head;
    }
}

补充一个更简洁的方法,该方法适合直接抽取出来作为一个方法使用,适用于一个算法中,需要多次翻转链表的情况

Python3代码:

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # 方法2
        # 首先判空
        if head == None:
            return head
        # 定义一个空的头节点
        pre_cur = None
        # nex节点可以不提前定义,看个人喜好
        nex = None
        # 只要节点不为空,就一直循环
        while head != None:
            # 用nex记录当前节点的下一个节点,否则后面就找不到了
            nex = head.next
            # 将当前节点的next属性赋值为pre_cur,也就是相当于令当前节点指向了前面一个节点
            head.next = pre_cur
            # 将pre_cur移动到下一个节点
            pre_cur = head
            # 将head移动到一开始记录的head节点的下一个节点处
            head = nex
        # 循环完成后pre_cur已经移动到原链表的最后一个节点处,也就是新链表的头节点,直接返回即可
        return pre_cur

Java代码:

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null){
        return head;
    }
    ListNode pre_cur = null;
    // 这里next一定要提前定义,其他地方和python基本一致
    ListNode next = null;
    while (head != null){
        next = head.next;
        head.next = pre_cur;
        pre_cur = head;
        head = next;
    }
    return pre_cur;
  }
}
   
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值