初级算法——反转链表

题目

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

 解法一:三指针迭代法

        反转链表最大的问题在于当该结点的next指向前一个结点后它的后一个结点就找不到了。为了能够找到前一个结点,我们可以再引入一个变量p,在next改变之前就往后移动,这样就可以通过p节点找到该节点的下一个结点了。

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;    //该节点的前一个
        ListNode cur = head;    //该节点
        if(head == null){
            return null;
        }
        while(cur.next != null){
            ListNode n = cur.next;    //该节点的后一个
            cur.next = pre;
            pre = cur;
            cur = n;
            n = n.next;
        }
        cur.next = pre;
        return cur;
    }
}

解法二:栈存储法

        提到倒置,我们可以联想到数据结构栈。栈的放入取出就是一次顺序的倒置。

class Solution {
    public ListNode reverseList(ListNode head) {   
        Stack<ListNode> s = new Stack<ListNode>();
        if(head == null){
            return null;
        }
        while(head.next != null){
            s.push(head);
            head = head.next;
        }
        s.push(head);    //还有最后一个没入栈
        ListNode newHead = new ListNode();
        ListNode p = newHead;
        while(!s.isEmpty()){
            ListNode n = s.pop();    //结点需要新建,而不能直接对取出的结点进行连接
            p.next = n;
            p = n;
        }
        p.next = null;    //将最后一个结点的next置空
        return newHead.next;
    }
}

注意:一定记得将最后一个结点的next置空, 否则由于它的next本身指向的是前一个结点,就会倒置最后两个结点互指,从而导致循环

解法三:头插法

我们知道链表有两种插入结点的方法,头插和尾插。当我们把链表从头开始遍历,然后新建链表进行头插操作,不就可以实现链表的倒置了吗?

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode newHead = new ListNode();
        while(head != null){
            ListNode p = new ListNode();    //每次创建一个结点
            p = head;   //让其与原链表的头指针所指结点相等
            head = head.next;   //原链表头指针移动
            p.next = newHead.next;  
            newHead.next = p;   //这两行为头插
            
        }
        return newHead.next;
    }

注意:head = head.next的位置必须在头插之前,否则由于p指针指向的就是head结点,头插会直接改变head的next,导致head = head.next失效。

解法四:递归

递归的适用情况需满足一下三点:

  • 大问题可以拆成两个子问题
  • 子问题的求解方式和大问题一样
  • 存在最小子问题

对于反转链表我们可以将其拆解为反转头节点和剩下的结点。

  1. 头节点怎么反转?就是头节点的下一个结点的next指向头节点,头节点的next置空。
  2. 其它结点和头节点的求解方式一样吗?当然一样了,都是该节点和后一个结点的next转换
  3. 存在最小子问题吗?存在,当没有下一个结点时

那么我们就可以使用递归方法来做,返回新的头节点。

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode newNode = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newNode;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值