【数据结构】反转链表

这篇博客探讨了如何反转单向链表的方法。首先介绍了使用五个指针来实现链表反转,但这种方法较为复杂。接着,提出了只需遍历一次链表的优化方案,通过记录头指针和临时节点,实现更简洁的反转过程。然而,在实际操作中,由于牛客网测试的Node结构限制,不能直接添加空节点,需要特殊处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一

  假设有下面这样一个单向链表
在这里插入图片描述
  想要将其反转输出,即得到4->3->2->1这样一个链表,我首先想到的是从拿到最后一个节点前面一个节点将他删除接在最后一个节点的后面依次下去不就可以了么
在这里插入图片描述
在这里插入图片描述
  但是这样就需要五个指针:

  1. head指针记录开始位置。
  2. mark指针记录原本的尾节点位置,因为当有节点接在原本尾节点之后就无法用next=null来找到原本的尾节点。
  3. pre指针记录mark的前一个节点,用于删除和重新拼接
  4. beforePre指针记录pre的前一个节点,要将他指向最后一个节点,用于下一次遍历
  5. 新的尾节点
    在这里插入图片描述

  但是这样是不是太麻烦了呢?五个指针记录,每次找到原尾节点的前一个值就需要一次遍历链表

方法二

  如何只用遍历一次就可以完成呢?先将前两个反转
在这里插入图片描述

在这里插入图片描述
  这样的关键就在于记录头指针(不是head,而是p,因为head第一次反转之后它就不在第一个了),保存head的下一个节点信息,因为要将head接在下下一个节点上(就像删除一样),所以需要一个临时节点(next)保存head.next的信息。
代码

public class Solution {
    public Node ReverseList(ListNode head) {
    if(head.head==null){
            return null;
        }
        /*ListNode是一个封装链表,而不是节点所以要将他的head取出来*/
        Node headNode = head.head;
        Node p = new Node();
        p.next=headNode;
        while (headNode.next!=null){
            /*将当前节点的下一个节点保存下来*/
           Node next = headNode.next;
           /*删除下一个节点p -> 1 -> 3-> 4->5*/
           headNode.next = next.next;
          /*将要反转的的节点反转p -> 2 -> 1 -> 3-> 4->5*/
           next.next=p.next;
           p.next = next;
        }
        return p;
    }
}

  然后我发现牛客网测试通不过,因为他给的Node结构如下

public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

  他的node不允许创建空节点,因此不能直接添加在p后面,因为他是头节点,而要直接改变p的值就需要一个临时节点将头节点信息保存下来

public class Solution {

    public ListNode ReverseList(ListNode head) {
        
        ListNode p = head;
        if(head==null){
            return null;
        }
        while (head.next!=null){
            /*将当前节点的下一个节点保存下来*/
           ListNode next = head.next;
            /*            p               	*/
            /*            |              	*/
           /*删除下一个节点 1 -> 3-> 4->5    	*/
            /*            |               	*/
            /*            head            	*/
           head.next = next.next;
            /*             p                    */
            /*             |                    */
            /*反转节点      2 -> 1 -> 3-> 4->5   */
            /*                  |               */
            /*                 head             */
            /*因为p节点是真正的头节点会不断改变,因此临时节点temp保存之前的信息*/
            ListNode temp = p;
            p =  next;
            /*完成链表链接*/
            p.next = temp;
        }
        return p;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值