LeetCode-数据结构-反转链表

力扣题目地址:https://leetcode-cn.com/problems/reverse-linked-list/

首先看题目:反转一个单链表。

示例

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

先不管什么进阶,不管黑猫白猫,只要能抓到耗子就是好猫。我们就是用最笨的方法也得把这道题给解决喽。

解决思路
首先明白我们要干啥,反转链表。最简单的方法是啥?就是把链表遍历一遍,取出所有的值,然后再反着给他拼回去不就行了。

实践代码
首先加入题目中给的 ListNode 类

package com.gyx.util;

/**
 * 节点类
 * @author GeYuxuan 2020/02/29 17:09
 */
public class ListNode {

    /**
     * 节点值
     */
    int val;

    /**
     * 下一个节点引用
     */
    ListNode next;

    /**
     * 构造函数,初始化设置val值
     * @param x
     */
    ListNode(int x){
        val = x;
    }
}

然后我们开始我们的解题之旅:

  1. 取出所有链表节点值。
  2. 放入一个List中存储。
  3. 反向循环拼接链表节点。

代码实现如下:

/**
     * 反转链表 - 不用脑子的解法
     * @param head
     * @author GeYuxuan 2020-03-02 22:08:57
     * @return com.gyx.util.ListNode
     */
    public ListNode reverseList(ListNode head) {
        List<Integer> list = new ArrayList<>();
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        while (head != null){
        	//1.2.两步一起,取值然后放入list
            list.add(head.val);
            //移动指针引用,指向下一个节点
            head = head.next;
        }
        //反向循环拼接链表
        for (int i = 0 ;i < list.size(); i++){
            cur.next = new ListNode(list.get(list.size()-i));
            cur = cur.next;
        }
        return pre.next;
    }

然后我们测试一下:

package com.gyx.util;

/**
 * description
 * @author GeYuxuan 2020/02/29 17:35
 */
public class Test {

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);
        Solution solution = new Solution();
        ListNode result = solution.reverseList(head);
        while (result != null){
            System.out.println(result.val);
            result = result.next;
        }
    }
}

打印结果: 5 4 3 2 1

ok,这就是我们最笨的解法了。这种解法太笨了,有点暴力破解的意思。

所以现在我们来看看进阶的迭代解法。

迭代的意思就是不断循环调用相同的代码,但是每一次的初始值使用上一次的结果。

其实我们昨天两数相加的题目里面也用到了迭代,在链表中循环取值并打印出来,这就算一个简单的迭代了。

我们现在来考虑反转链表迭代的思路:

  1. 需要保存下一个节点,保证能循环当前链表。
  2. 将当前节点的next节点换成上一个节点。(反转)
  3. 移动pre指针将当前节点变成下一个节点的下一个节点。
  4. 将保存的下一个节点赋给当前节点,迭代下一个链表节点。
/**
     * 反转链表 - 迭代
     * @param head
     * @author GeYuxuan 2020-03-02 22:08:57
     * @return com.gyx.util.ListNode
     */
    public ListNode reverseList1(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            //1.保存下一个节点
            ListNode nextNode = cur.next;
            //2.修改当前节点的next节点 为 上一个节点
            cur.next = pre;
            //3.移动pre指针,保证当前节点是下一个节点的下一个节点
            pre = cur;
            //移动指针,移向下一个元素
            cur = nextNode;
        }
        return pre;
    }

其实迭代的解题方法我也说的不是很清楚怎么完成反转的。这周周末会补上一张自己画的gif动图,这样不仅可以帮助大家,也可以帮助我自己更好的理解迭代算法。
递归算法就更不用说了,感觉脑子不够用了,这周周末一起补上详解;一定得啃下它。

未完待续:

  1. 迭代算法gif动图。
  2. 递归算法详解。

不忘初心,砥砺前行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值