链表的专用题型-链表的经典算法(反转链表)

题目

反转链表_牛客题霸_牛客网 (nowcoder.com)

逻辑实现

这里我们采取第二种方式来讲解:

转链表是计算机算法和数据结构中一个常见的题目。链表是一种常见的基础数据结构,它由一系列结点组成,每个结点包含数据域和指向下一个结点的指针。

要反转一个链表,基本的思路是遍历原链表,在遍历过程中改变每个结点的指针方向,使其指向前一个结点,从而得到一个新的链表,其结点的顺序与原链表相反。

下面是反转单向链表的一般步骤:

  1. 定义三个指针:pre(前驱结点)、cur(当前结点)和next(下一个结点)。
  2. pre初始化为NULL,它将用来跟踪反转后的链表的末尾。
  3. 从链表的头结点开始,将cur指向头结点,next指向cur的下一个结点。
  4. 在每次迭代中:
    • cur的下一个结点设置为pre,即改变指针方向。
    • pre向前移动一步,即pre现在指向cur
    • cur向前移动一步,即cur现在指向next
    • 如果cur不是链表的最后一个结点,则设置nextcur的下一个结点。
  5. cur变为NULL时,说明已经遍历完整个链表,此时pre指向的就是新的头结点。

单趟实现

循环实现

代码实现

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param head ListNode类 
 * @return ListNode类
 */

 //三指针解决
 //保存上一个节点,当前节点,下一个节点
struct ListNode* ReverseList(struct ListNode* head ) {
    if(head==NULL)
        return NULL;
    // 这里的前后指针初始的时候需要指向空,因为可能存在几种情况,比如是空,prev是当前节点的上一个节点,本身就是空,所以初始的时候需要指向null
    struct ListNode* cur=head;
    struct ListNode* prev=NULL;
    struct ListNode* next=NULL;
    //这一步放到这里的关键在于,节点的尾部的下一个节点刚好是null,所以放在这个位置,不然导致死循环
    while (cur) {
        next=cur->next;
        cur->next=prev;
        prev=cur;
        cur=next;
    }
    //这里需要知道的是,最后cur和next都会越界,所以我们需要返回的数值是prev
    return prev;
}

解释:

  1. 函数定义

    struct ListNode* ReverseList(struct ListNode* head);

    这个函数接受一个 ListNode 类型的指针 head,它是链表的头节点。函数返回一个 ListNode 类型的指针,即反转后链表的新头节点。

  2. 空链表检查

    if(head == NULL) return NULL;

    如果传入的头节点 headNULL,表示链表为空,直接返回 NULL

  3. 初始化指针

    struct ListNode* cur = head; struct ListNode* prev = NULL; struct ListNode* next = NULL;

    • cur 用于遍历链表,初始化为头节点。
    • prev 指向当前节点的前一个节点,初始化为 NULL
    • next 用于临时存储当前节点的下一个节点,初始化为 NULL
  4. 反转链表

    while (cur) { next = cur->next; cur->next = prev; prev = cur; cur = next; }

    这是一个循环,遍历原始链表的所有节点:

    • 存储当前节点 cur 的下一个节点到 next
    • 将当前节点 cur 的 next 指针指向其前一个节点 prev,实现反转。
    • 将 prev 更新为当前节点 cur
    • 将 cur 更新为 next,即移动到下一个节点。
  5. 返回新头节点

    return prev;

    循环结束后,prev 将指向原始链表的最后一个节点,它成为了反转后链表的新头节点。

  6. 循环的结束条件: 当 curNULL 时,循环结束。此时,原始链表的尾节点的 next 指针已被设置为 NULL,避免了死循环。

  7. 函数的返回值: 函数返回 prev,它是反转后链表的新头节点。

这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们需要遍历链表中的每个节点一次。空间复杂度是 O(1),因为我们只使用了有限数量的额外指针变量,不依赖于输入链表的大小。

注意事项

1,

 // 这里的前后指针初始的时候需要指向空,因为可能存在几种情况,比如是空,prev是当前节点的上一个节点,本身就是空,所以初始的时候需要指向null

2,

这里需要了解的是,这里我们最后的cur和next都会产生越界行为,所以我们最后返回的是prev

3,

这里的cur->next=prev位置不能放到最后,应该放到第二个,因为我们最后指向的空节点

所以,我们应该先指向上个节点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值