链表是数据结构中最基本的一种结构,看我如何驯服他

143 阅读2分钟

「这是我参与2022首次更文挑战的第33天,活动详情查看:2022首次更文挑战」

一、题目描述

反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

image-20210520171256340

二、思路分析

  • 链表操作正常就是循环遍历链表从而进行操作。在leetcode官网中也给了我们提示实现反转可以通过迭代和递归两种方式。

  • 下面我们通过两种方式来分析下实现逻辑

  • 其实递归在理解上应该更好的理解。递归是先进入最底层开始执行。递归和迭代在执行的方向上是相反的。

  • 递归最终先执行右侧相邻节点。只需要将两个指针指向修改就可以了。递归是最方便的。但是执行上没有迭代性能高

 public ListNode reverseList(ListNode head) {
     if (head == null) {
         return head;
    }
     return digui(head, head.next);
 }
 ​
 public ListNode digui(ListNode preNode , ListNode head) {
     if (head == null) {
         return preNode;
    }
     ListNode diguiNode = digui(head, head.next);
     head.next = preNode;
     preNode.next=null;
     return diguiNode;
 }

四、总结

  • 往往最简单的思维性能并不是最优的。
  • 在链表的操作中,借助辅助节点是必要的。往往我们需要辅助节点来临时存储交换节点用来

补充

  • 首先我们需要借助于独立的三个节点来完成迭代反转的操作。分别是preNodenextNodecurrentNode 。 分别用于表示现阶段的前置节点、后置节点、当前节点。
    • 下面我们通过动画来解释下相邻的两个节点是如何依赖这三个节点实现反转的

    • 两两节点都是这么操作的。当操作到最后的时候preNode就是我们原链表中的最后的节点,反转之后恰恰是我们反转链表的开始节点所以直接将preNode返回即可

 public ListNode reverseList(ListNode head) {
     ListNode preNode = null;
     ListNode nextNode = null;
     ListNode currentNode = head;
     while (currentNode != null) {
         nextNode = currentNode.next;
         currentNode.next = preNode;
         preNode = currentNode;
         currentNode = nextNode;
    }
     return preNode;
 }