首页 > 其他分享 >单链表OJ题(2):反转链表(三指针法)、找中间节点(快慢指针)

单链表OJ题(2):反转链表(三指针法)、找中间节点(快慢指针)

时间:2024-11-03 19:46:41浏览次数:3  
标签:n3 ListNode OJ next 链表 NULL 节点 指针

目录

1.反转链表

反转链表总结:

2.链表的中间节点(快慢指针法)

快慢指针法总结


1.反转链表

在这道题中,我们需要把一个单链表反转它们的指向,这里,我们给出了一个好理解的简单解法,就是用三个指针去解决这道题。 先给出完整的代码。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    //创建头指针
    ListNode* n1 = NULL;
    ListNode* n2 = head;
    if(n2==NULL){
        return NULL;
    }
    ListNode* n3 = n2->next;
    while(n2){
        n2->next=n1;
        n1 = n2;
        n2 = n3;
        if(n3)
            n3=n3->next;
    }
    return n1;
}

假设,我们的原链表为head,我们申请了n1,n2,n3三个指针,其中,n1初始化为NULLn2初始化为head(图中的第一个节点)n3初始化为head->next(也就是图中的第二个节点) 

 

第一次操作:

第二次操作:

 

第三次操作:

第四次操作:(注意:最后一次操作,n3的指针指向,不能让n3出现NULL->NULL的情况)

然后,我们的步骤如下:

1、遍历原链表中的每个节点,每次遍历,先使n1的指针指向n2的节点(n1=n2)然后让n2的节点指向n3(n2=n3)最后让n3的节点指向n3的下一个节点(n3=n3->next) 

2、注意,要在循环中判断以下n3的指针指向,防止出现NULL->NULL的情况。

反转链表总结:

这里面最重要的是我们要改变当前的节点的指向关系的时候,注意要先把当前节点指向的下一个节点的指针保存下来。如果我们不保存就改变指向关系的化,就会导致一个严重的错误,我们原链表中当前节点的下一个节点就找不到了。如下图,当我们遍历原链表的时候,我们需要让第一个链表的节点指向NULL但是我们没有存储第二个节点的地址当我们改变了指向让第一个节点的地址为NULL的时候原链表后面的节点就没办法找到

 

这个时候,我们就需要在改变当前节点指向关系前将这个节点的next域存储起来,这样我们就可以实现通过n3找到原链表节点通过n2就可以改变当前链表的指向关系。 

2.链表的中间节点(快慢指针法)

 

(1)在看到这个题的时候,我们能够都想到的同用解法是用计数器来做 ,下面是具体步骤:

1、首先我们遍历原链表,定义一个变量count存储节点的个数然后将每个节点都做+1的操作,这样我们就得到了链表的节点总个数count

2、然后,我们对count/2得到中间节点的位置然后再次遍历原链表找到下标为:count/2的位置上的节点,并返回

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode* pcur = head;
    int count = 0;
    while(pcur){
        count++;
        pcur = pcur->next;
    }
    pcur = head;
    count /= 2;
    while(count--){
        pcur = pcur->next;
    }
    return pcur;
}

 (2)这里提供一种很巧妙的解题方法,我们只需要遍历一遍链表就能够得到链表中间的位置,这个就是我们接下来介绍的快慢指针法了。

先给出代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    if(head==NULL){
        return NULL;
    }
    //定义快慢指针
    ListNode* slow ,*fast;    
    slow = fast = head;
    while(fast && fast->next){
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

1、刚开始,我们创建两个指针slow和fast都指向头节点.

2、接下来,我们规定,slow每次走一个节点fast每次走两个节点,当遍历结束时,slow指针指向的节点就是我们需要的中间节点

3、循环结束的条件fast!==NULL && fast->next!=NULL

我们继续深入解析以下结束的循环条件是如何得到的,这就得要根据节点个数是否为奇数和偶数来确定。 

1)当讨论的节点个数为偶数的时候: 

阶段1:

阶段2: 

阶段3:

 从这里可以得到,当我们得fast指针指向NULL时循环结束,此时,slow指向得节点正好是我们需要得中间节点。

2)当讨论的节点个数为奇数的时候: 

阶段1:

阶段2:

阶段3:

从这里,我们可以看出来,当fast的next指向为NULL时我们的循环结束,此时,slow指针指向的节点就是我们的中间节点。

然后,我们得出结论,当fast和fast->next有一个为NULL时我们的循环条件就结束,此时我们的slow指针指向的节点就是中间节点。 (这里的)

快慢指针法总结:

这里的快慢指针法可以很快的找到我们所需要的单链表中的中间节点,代码量也很少,是一个很不错的解题思路,在涉及到用中间节点解题的时候,可以参考以下这个方法。 

标签:n3,ListNode,OJ,next,链表,NULL,节点,指针
From: https://blog.csdn.net/2301_80966914/article/details/143273769

相关文章

  • 单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
    目录 一、合并两个有序链表 二、链表分割三、链表的回文结构u解题的总体思路: 合并两个有序链表:首先创建新链表的头节点(哨兵位:本质上是占位子),为了减少一些判断情况,简化操作。然后我们再创建俩个指针分别指针两个单链表的头,然后遍历比较,将两个指针指向节点的最小值接......
  • 深入理解指针2(数组)
    1:数组名的理解数组名是数组首元素的地址也就是arr=&arr[0]但是有两种例外的情况1:siezof(数组名)sizeof中单独存放数组名,这里的数组名是数组的整个地址,计算的是整个数组的大小,单位是字节。2:&数组名这里的数组名表示的是整个数组,取出的整个数组的地址整个数组的地址和数......
  • LeetCode 19. 删除链表的倒数第 N 个结点(java)
    目录题目描述:代码:第一种:第二种:题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。示例1:输入:head=[1,2,3,4,5],n=2输出:[1,2,3,5]示例2:输入:head=[1],n=1输出:[]示例3:输入:head=[1,2],n=1输出:[1]代码:第一种:......
  • 智能指针介绍和方法
    普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型unique_pt......
  • 深入理解指针3
    1.数组名的理解2.使⽤指针访问数组3.⼀维数组传参的本质4.冒泡排序5.⼆级指针6.指针数组7.指针数组模拟⼆维数组1.数组名的理解我们在上面的图中就可以看见。这⾥我们使⽤&arr[0]的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且是数组⾸......
  • 【STL_list 模拟】——打造属于自己的高效链表容器
    一、list节点​list是一个双向循环带头的链表,所以链表节点结构如下: template<classT> structListNode { Tval; ListNode*next; ListNode*prve; ListNode(intx) { val=x; next=prve=this; } };二、list迭代器2.1、list迭代器与vector......
  • 【C语言学习】7步轻松掌握C语言链式结构,你也能成为高手!与数组说拜拜,链表你好
    ......
  • 东华大学oj航班时间
    大家来搜到我这篇博客可能是出于两个目的,一种是真的没有思路,另一种呢是不知道该怎么输入。注:本题我只用到函数而且用法简单。航班时间时间限制:1s类别:循环结构->较难问题描述【问题背景】小h前往美国参加了蓝桥杯国际赛。小h的女朋友发现小h上午十点出发,上午十二点......
  • CF1658E Gojou and Matrix Game
    题意题解设f[i,j]表示(i,j)先手必胜/必败则全局max一定必败,因为先手走出去后手走回来,重复无限次后必输然后全局max外(距离>k)的必胜,因为可以走到全局max之后可以发现,下一个必败的是全局max范围内的次max,因为次max不能①走出全局max范围②走到全局max③走到一个比自己小的数(......
  • 三数之和(双指针法)
    给你一个整数数组 nums ,判断是否存在三元组 [nums[i],nums[j],nums[k]] 满足 i!=j、i!=k 且 j!=k ,同时还满足 nums[i]+nums[j]+nums[k]==0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。示例1:输入:nums=[-1,0,......