算法(5)--链表(2)反转链表 力扣206

本人是刷《代码随想录》这本书时记录一下自己的学习笔记

思路

这道题有三个思路:

1、建立一个新链表,用头插法不断往新链表插入数据;

2、使用原链表,用双指针法;

3、递归;

建议先使用双指针的方法写完,再写递归的方法,会使自己思路更清晰

头插法

定义一个新链表,然后使用头插法不断建立节点

public ListNode reverseList(ListNode head) {
        //采用头插法反转
        ListNode h = new ListNode(-1);//建立头结点,为了返回新链表
        while(head!=null){
            ListNode temp = new ListNode(head.val);//建立新链表的节点
            temp.next = h.next;
            h.next = temp;
            head = head.next;
        }
        return h.next;
    }

优点:容易理解

缺点:新建一个链表,浪费内存空间

双指针法

        反转链表的本质就是改变链表的next指针的指向

        我们定义在链表里定义两个指针,一个是准备改变next节点的指针cur,一个是cur需要指向的节点的指针pre原链表中cur的前一个节点),然后使cur.next指向pre,这样就达到了反转后链表节点的指向。

        举一个例子:

                原来的链表1->2 ->null , pre = 1 , cur = 2 

                改变中: cur.next = pre  (2-->1)   , 像这样翻转前我们需要再cur.next指针改变前保存cur的下一个节点,下图是《代码随想录》中的示意图

代码:

public ListNode reverseList(ListNode head) {
        //双指针,在原有链表上进行操作
    //pre cur 使cur的next指针指向pre
        //口->口->口->口->口
        //口<-口<-口<-口<-口
        ListNode pre = null;
        ListNode cur = head;
        while(cur!=null){
            ListNode temp = cur.next;//保存cur的下一个节点,以防链表丢失
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }

递归法

从前往后改变指针

        递归方法的思路和双指针很像,大概就是把循环的条件变成if,然后不需要手动赋值下一个节点。

        从前往后改变指针的意思是,先改变next指针,在向下递归,最后返回原链表的尾结点

public ListNode reverseList(ListNode head) {
        //递归写法
        return reverse(null,head);
    }
    public ListNode reverse(ListNode pre,ListNode cur){
        if(cur==null){
            return pre;
        }
        ListNode temp = cur.next;
        cur.next = pre;    //改变next指针的指向
        return reverse(cur,temp);    //与双指针里的循环很像
    }

从后往前改变指针

        从后往前递归的意思是,先递归到原链表的尾结点,然后改变其next指针的指向,注意一个的是这个方法的返回值一直都是原链表的尾结点。

public ListNode reverseList(ListNode head) {
        // 边缘条件判断
        if(head == null) return null;
        if (head.next == null) return head;
        
        // 递归调用,翻转第二个节点开始往后的链表
        ListNode last = reverseList(head.next);
        // 翻转头节点与第二个节点的指向
        head.next.next = head;
        // 此时的 head 节点为尾节点,next 需要指向 NULL
        head.next = null;
        return last;  //返回的是同一个节点,就是原链表的尾结点
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值