C++相交链表和反转链表详解

 更新时间:2021年08月19日 10:27:06   作者:久病成良医  
这篇文章主要介绍了C++相交链表和反转链表,结合实例形式分析了C++相交链表和反转链表的原理、实现方法及相关注意事项,需要的朋友可以参考下

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

在这里插入图片描述

思路

简单来说,就是求两个链表交点节点的 指针。 这里同学们要注意,交点不是数值相等,而是指针相等。

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

在这里插入图片描述

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

在这里插入图片描述

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到焦点。

否则循环退出返回空指针。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA=headA;
        ListNode* curB=headB;
        int lenA=0;
        int lenB=0;
        while(curA!=nullptr){  // 求链表A的长度
            lenA++;
            curA=curA->next;
        }
        while(curB!=nullptr){  // 求链表B的长度
            lenB++;
            curB=curB->next;
        }
        //现在的curA,curB已经指向最后一个节点了,需要重新指向头结点
        curA=headA;
        curB=headB; 
        if(lenA<lenB){  //假设链表A的长度大于链表B,否则交换
            swap(lenA,lenB);
            swap(curA,curB);
        }
        //gap是两个链表长度的差值
        int gap=lenA-lenB; // gap=lenA-lenB 错误,要有返回类型
        while(gap){     // 让curA和curB在同一起点上(末尾位置对齐)
            gap--;
            curA=curA->next;  
        }
        while(lenB){   // 遍历curA 和 curB,遇到相同则直接返回
            if(curA==curB)
                return curA; // return curA(val) 返回节点中的值,这个写法是错误的  直接return curA
            curA=curA->next;
            curB=curB->next;
            lenB--;
        } 
        return nullptr;  //没有交点则返回空
    }
};

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

示例 1:

输入:head = [1,2,3,4,5]

输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]

输出:[2,1]

示例 3:

输入:head = []

输出:[]

双指针思路

首先判断链表是否为空,为空则返回nullptr。

接下来定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。

然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。

为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。

接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。

最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr)  //对空链表的判断
            return nullptr;
        ListNode* per=nullptr;
        ListNode* cur=head;
        ListNode* temp; //建立一个指针
        while(cur){  //没必要写 while(cur!=nullptr),写了这个还要判断cur,会浪费时间,直接cur就可以
            temp=cur->next; //保存cur的下一个节点
            cur->next=per; //cur的下一个节点指向per,实现反转
            per=cur;  //cur=per;错误,是把cur的节点赋值给per
            cur=temp; //temp=cur;错误,是把temp(原来的cur->next)的节点赋值给cur
        }
        return per;
    }
};

递归

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverse(ListNode* per,ListNode* cur){  //返回的是一个链表,其返回值是指针
        if(cur==nullptr)  //递归的终止条件
            return per;
        ListNode* temp=cur->next;
        cur->next=per;
        return reverse(cur,temp); // 调用要写return
    }
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr) //链表判空
            return nullptr; 
        return reverse(NULL,head); // 调用要写return
    }
};

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • C语言新手入门之格式化输出和变量类型

    C语言新手入门之格式化输出和变量类型

    这篇文章主要给大家介绍了关于C语言中格式化输出和变量类型的相关资料,文中的教程非常适合新手零基础的朋友们参考学习,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • OpenCV透视变换应用之书本视图矫正+广告屏幕切换

    OpenCV透视变换应用之书本视图矫正+广告屏幕切换

    透视变换是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面绕迹线旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。本文将为大家介绍两个OpenCV透视变换应用,需要的可以参考一下
    2022-08-08
  • 浅谈C++流库的基本结构

    浅谈C++流库的基本结构

    本文主要介绍了浅谈C++流库的基本结构,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • C语言归排与计排深度理解

    C语言归排与计排深度理解

    这篇文章主要为大家详细的介绍了C语言中计数排序和归并排序,归并排序是创建在归并操作上的一种有效的排序算法,计数排序不用比较两个数的大小,感兴趣的朋友可以参考阅读
    2023-04-04
  • 利用C++实现矩阵的相加/相称/转置/求鞍点

    利用C++实现矩阵的相加/相称/转置/求鞍点

    利用C++实现矩阵的相加/相称/转置/求鞍点。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C++中constexpr与模板元编程的基础、常见问题、易错点及其规避策略

    C++中constexpr与模板元编程的基础、常见问题、易错点及其规避策略

    C++编译时计算允许程序在编译阶段完成计算任务,constexpr与模板元编程是C编译时计算的两把利剑,它们不仅能够提升程序的性能,还能增强代码的健壮性和可维护性,通过避开本文阐述的易错点,开发者可以更加得心应手地运用这些特性,编写出既高效又优雅的C代码
    2024-06-06
  • C语言程序设计50例(经典收藏)

    C语言程序设计50例(经典收藏)

    本篇文章是对C语言程序设计的50个小案例进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C语言中字符串库函数的实现及模拟

    C语言中字符串库函数的实现及模拟

    C语言中有很多数据类型,比如int(整数类型)、char(字符类型)、以及浮点型的double(双精度)等。但是有一点就是我们发现这里并没有提到我们常见的有关字符串的类型。本文为大家介绍了C语言中字符串库函数的实现及模拟,需要的可以参考一下
    2022-11-11
  • C++实现LeetCode(171.求Excel表列序号)

    C++实现LeetCode(171.求Excel表列序号)

    这篇文章主要介绍了C++实现LeetCode(171.求Excel表列序号),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++ assert()函数用法案例详解

    C++ assert()函数用法案例详解

    这篇文章主要介绍了C++ assert()函数用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09

最新评论