反转链表I解题思路

声明:该题是leecode206

题目

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

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

 示例 2:

 输入:head = [1,2] 输出:[2,1]

示例 3:

输入:head = [] 输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

 链表的数据结构如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {

    }
}

 迭代法

迭代法,算法的核心,就是在每一次迭代的时候,将相邻的两个节点之间的指针进行反转。

 我们来看一次反转,需要做哪些事情。

假设我们当前节点是1,

ListNode current = head;

我们要将1.next指向它的前一个节点,现在1的前一个节点是空,我们设

ListNode prev = null;

 我们把 1.next = prev = null。但当我们这么做的时候,整个单向链表就断了,1后面的元素就找不到了,所以在这之前,我们需要一个额外的变量来存储原来 1.next 的值。

ListNode next = current.next;

current.next = prev;

 这样,我们就完成了对1的修改,那我们的一次迭代结束了么,还没有,

我们还需要将current指针往下移动,让它指向下一个节点。

current = next;

但当我们将current指向2的时候,下一次迭代,2.next需要指向1,但是这个时候,我们找不到1,因为没有变量引用1。所以在将current指向2之前,我们还需要先将1的引用赋值给prev,让它指向1。

prev = current;

current = next;

 那迭代在什么情况下结束呢?

current刚开始指向1,然后迭代着指向2、指向3、指向4、指向5,

是不是当current变量指向null的时候,迭代就结束了,这个时候的prev,就是我们反转后新的链表的头节点。

 完整代码如下

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode current = head;
        ListNode prev = null;
        while (current != null) {
            // 1、暂存当前节点next引用变更前的后续节点,防止链表丢失
            ListNode next = current.next;
            // 2、将前一个节点的引用赋值给当前节点的next
            current.next = prev;
            // 3、将当前节点赋值给prev变量
            prev = current;
            // 4、将当前节点指针往下迭代
            current = next;
        }
        return prev;
    }
}

递归法

其实递归法跟上面的迭代法是如出一辙的。我们看上面的迭代法,其中有两个变量,是特别重要。

一个是current,它指向当前节点,然后在每一次迭代后,指向下一个节点;

一个是prev,它指向当前节点的上一个节点,然后在每一次迭代后,指向当前节点。

就是这种变换,给了我们层层往下递归创造了条件。

那我们思考一下,递归的结束条件是什么?

是不是也是当 current == null 的时候,递归就结束了,这个时候的头节点,不就是 prev么?

递归代码呼之欲出:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        // 初始的prev节点是空
        return recursion(null, head);
    }

    public ListNode recursion(ListNode prev, ListNode current) {
        if (current == null) {
            return prev;
        } else {
            // 1、暂存当前节点next引用变更前的后续节点,防止链表丢失
            ListNode next = current.next;
            // 2、将前一个节点的引用赋值给当前节点的next
            current.next = prev;
            // 3、将当前节点赋值给prev变量
            prev = current;
            // 4、将当前节点指针往下迭代
            current = next;
            // 5、递归进行指针变换
            return recursion(prev, current);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值