首页 > 其他分享 >Day4||24.两两交换链表中的节点|19.删除链表的倒数第n个结点|面试题:链表相交|142.环形链表Ⅱ

Day4||24.两两交换链表中的节点|19.删除链表的倒数第n个结点|面试题:链表相交|142.环形链表Ⅱ

时间:2024-09-15 10:22:25浏览次数:3  
标签:24 面试题 ListNode cur next 链表 节点 指针

24.两两交换链表中的节点

题目:24. 两两交换链表中的节点 - 力扣(LeetCode)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

图解思路

首先,虚拟头结点挺方便链表进行增删改操作的。本题操作用到三个指针,cur指针指向虚拟头结点,因为要交换的是第一第二个节点,往后的操作都是cur要指向交换节点的前一个节点。

步骤一cur先指向要交换的第二个节点,然后特别说明要实现步骤二,就得事先用临时指针1储存第一个节点的地址(考虑到单向链表的特性),同理, 临时指针2要保留第二个节点的下一个节点的地址(因为步骤二完成时就失去了和下一个节点的连接)。最后释放虚拟头结点就行。

代码 

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
     ListNode*dummyhead=new ListNode(0);
     dummyhead->next=head;
     ListNode*cur=dummyhead;
     while(cur->next!=NULL&&cur->next->next!=NULL)
     {
      ListNode*tmp=cur->next;
      ListNode*tmp1=cur->next->next->next;//记录要交换的第一个节点和第二个节点的下一个
      //两两交换过程
      cur->next=cur->next->next;
      cur->next->next=tmp;
      cur->next->next->next=tmp1;
      
      //更新cur的指向,就是下一个两两交换元素的前一位
      cur=cur->next->next;
     }
     ListNode*result=dummyhead->next;
     delete dummyhead;
     return result;
    }
};

最后返回头结点时,注意先保存dummyhead->next的值不然释放dummyhead的时候找不到头结点的位置。

 19.删除链表的倒数第n个结点

题目:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

思路,快慢指针法+虚拟头结点。

找到倒n个节点的关键就是快指针比慢指针先走多少步。但是,快指针要快n+1步是要让慢指针指向被删节点的前一个节点。

模拟一遍走法就比较好理解了。复习到一个点就是要删除哪个节点就让指针指向该节点的前一个节点,然后同步移动直到快指针指向null。特别留意c++中还有手动释放节点。

代码

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode*dummyhead=new ListNode(0);
    dummyhead->next=head;
    ListNode*fast=dummyhead;
    ListNode*slow=dummyhead;
    n++;//+1是因为要指向被删节点的前一个
    while(n--&&fast!=NULL)//快指针快n步
    {
        fast=fast->next;
    }
    while(fast!=NULL)//快慢指针同步移动
    {
        fast=fast->next;
        slow=slow->next;
    }
    ListNode*tmp=slow->next;//删除,手动释放
    slow->next=tmp->next;
    delete tmp;

    return dummyhead->next;
    }
};

图示理解

  面试题:链表相交 

题目:面试题 02.07. 链表相交 - 力扣(LeetCode)

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

图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

数学方法思路:(参考题解)

构建两个指针A和B,分别指向两个链表的表头,A先遍历headA,在遍历headB,直到达到首个公共节点node,共走步数b+(a-c)。同理,B先遍历headB,在headA,达到node时停下,共走步数a+(b-c)。----其实就是让两个指针分别走一遍相交链表的所有节点,只是出发点不一样。

如下式所示,此时指针 A , B 重合,并有两种情况:

a+(b−c)=b+(a−c)
若两链表 有 公共尾部 (即 c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c=0 ) :指针 A , B 同时指向 null 。
因此返回 A 即可。

代码也比较简洁:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *A = headA, *B = headB;
        while (A != B) {
            A = A != nullptr ? A->next : headB;
            B = B != nullptr ? B->next : headA;
        }
        return A;
    }
};

 快慢指针

本题注意一个非常易错难以理解的点,就是求节点相交的指针,交点不是数值相等而是指针相等。如图

A,B链表在节点8相交之前都有一个相同值的节点,但它们不是相交的起始节点。我想,这是因为起始节点是从尾端开始数起的。

所以本题的思路是,

1.定义两个指针,分别指向两个链表的头结点

2.分别遍历链表,求出各自的长度

3.求两个链表的长度差,定A为较长的链表,并且指针cura比curb先走长度差个节点。(使两链表尾端齐平)

4.然后同时遍历直到指针相同,即找到相交节点,返回交点,否则返回空

代码

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode*curA=headA;
        ListNode*curB=headB;
        //获取链表长度
        int lenA=0,lenB=0;
        while(curA!=NULL)
        {
            curA=curA->next;
            lenA++;
        }
        while(curB!=NULL)
       {
        curB=curB->next;
        lenB++;
       }

        //易错点:遍历完之后两个指针没有重新指向表头
       curA=headA;
       curB=headB;
      
       if(lenA<lenB)
       {
        swap(lenA,lenB);
        swap(curA,curB);
       }
       //较长的链表多走n步
       int n=lenA-lenB;
       while(n--)
       {
       curA=curA->next;
       }
       

       while(curA!=NULL)
       {
        if(curA==curB)return curA;//如果指针相同,证明找到相交节点
        curA=curA->next;
        curB=curB->next;
       }
       return NULL;
    }
};

142.环形链表Ⅱ

题目:142. 环形链表 II - 力扣(LeetCode)

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

思路

 定义一个快慢指针,快指针总是比慢指针快一步,如果快指针遇到空指针,那么环不存在,如果遇到慢指针,环就存在。且,在环中时,快指针每走一步,就与慢指针更接近一步,而且,当它们相遇时,快指针至少比慢指针多走了一圈

如何找到入口,且看公式 快指针走了x+y+n(z+y),慢指针走了x+y,由于快指针比慢指针多走一步,所以有等式方程   

x+y+n(z+y)=x+y

化简移动: x=n(z+y)-y

提取一个z+y出来就是   x=(n-1)(z+y)+z(n>=1)

当n等于1时,快指针在环里转一圈就遇到了慢指针

同时,n=1时x等于z,那我们就可以安排两个指针,一个从头结点出发,一个从相遇节点出发,都同时移动一步,它们相遇的节点就是环的入口

n>1时说明快指针要在环里转n圈才能遇到慢指针,区别就是要找到入口节点时,从相遇节点出发的指针要在环里转(n-1)圈才能遇到从头结点出发的指针。

模拟图

转载于:https://www.yuque.com/xiaoshan_wgo/alog/pcenhscg4tmx6ogz 

动图: 

想象一下操场跑步。

代码

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode*fast=head;
        ListNode*slow=head;
        while(fast!=NULL&&fast->next!=NULL)//这里主要是考虑了链表节点个数奇偶数的问题
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)//找到相遇节点
            {
                ListNode*index1=fast;//从相遇节点出发
                ListNode*index2=head;//从头结点出发
                while(index1!=index2)//找环的入口
                {
                    index1=index1->next;
                    index2=index2->next;
                }
                return index1;
            }
        }
        //如果没找到环就返回空
        return NULL;
    }
};

今天就是快慢指针的加强使用,感觉自己运用得越来越熟练了,这就是参加训练营的意义吧,这几天做的题换做以前三天打鱼两天晒网的我得做两星期。

链表专题总结图: 

标签:24,面试题,ListNode,cur,next,链表,节点,指针
From: https://blog.csdn.net/2301_79865280/article/details/142260094

相关文章

  • SQL编程题复习(24/9/15)
    练习题x4010-114检索出course表中前3门课程的课号及课程名称的记录10-115检索出students表中“信息学院”的学生姓名、性别和出生日期的记录10-116检索出students表中所有系名的记录,要求结果中系名不重复10-117检索出sc表中‘C001’课程未登记成绩的学生学号(MSSQL)10......
  • 【2024研赛】【华为杯】2024 年研究生数学建模比赛思路、代码更新中.....
    ......
  • 链表的快速排序(C/C++实现)
    一、前言大家在做需要排名的项目的时候,需要把各种数据从高到低排序。如果用的快速排序的话,处理数组是十分简单的。因为数组的存储空间的连续的,可以通过下标就可以简单的实现。但如果是链表的话,内存地址是随机分配的,不能像数组那样通过下标就直接实现。所以在这里给大家介绍......
  • 2024年金典Java面试八股文
    1、什么是自动拆装箱 int和Integer有什么区别   难度系数:⭐基本数据类型,如int,float,double,boolean,char,byte,不具备对象的特征,不能调用方法。装箱:将基本类型转换成包装类对象拆箱:将包装类对象转换成基本类型的值java为什么要引入自动装箱和拆箱的功能?主要是用于jav......
  • 2024.09.14小红书
    1.小红的文章匹配小红书的第i篇文章有一个点赞数ai。小红认为,如果两篇不同的文章满足:点赞数通过位异或运算恰好得到k,那么这两篇文章是相似文章,即aixoraj=k。现在小红收集到了n篇文章的点赞数,请帮助她计算出有多少对(i,j)是相似文章。输入描述第一行输入两个整数n......
  • 【专题】2024新能源企业“出海”系列之驶向中东、东南亚报告合集PDF分享(附原数据表)
    原文链接: https://tecdat.cn/?p=37698在“双碳”目标引领下,中国新能源产业近年迅猛发展,新能源企业凭借技术革新、政策支持与市场驱动实现快速增长,在产业链完备、技术领先、生产效能及成本控制等方面优势显著。面对国内外环境不确定性增强的常态化态势,中国新能源企业积极开拓海外......
  • 2024.9.14
    DATE#:202409014ITEM#:DOCWEEK#:SATURDAYDAIL#:捌月拾贰TAGS<BGM="诀别无尽夏--YouzeeMusic"><theme=oi-contest><[NULL]><[空]><[空]>“每个夏天的句号都是窗外要烂掉的绿”A.上海时间限制:1s 内存限制:512MB 测评类型:传......
  • 2024.9.14
    今日总结:1:约数个数和这道题主要是一道数学题,主要的推到过程需要用到莫比乌斯反演,但是在求第一步用分块处理出1~n内的f(i)的值,再用线性筛求出u(i)的值和他的前缀和,我卡在了最后一步对原式进行数论分块点击查看代码#include<bits/stdc++.h>usingnamespacestd;constint......
  • 2024.9.13 总结(考 DP)
    (实际上是2024.9.14写的)本来以为是考DS的。()T1题目里给的那个性质可能是来干扰的。异或上右移一位的数,其实就是除了第一位(最左边的),算贡献的时候都要看这一位异或前一位是不是1。于是随便线性DP,状态里记一下当前位填0还是1就行了。DP数组状态的第一维可以不要,省空......
  • 2024.8.5
    现在是\(20:45\),场上只有三个小学生改出来\(\text{T4}\)了,你校小学生太可怕。不想写\(\text{T4}\)了,还有一个小时写写总结吧。今天大爆炸,无论是思维上还是码力上还是读题上。\(0+10+40+0\),真的要挂到地板上了(我发现一个规律,每次比赛\(\text{T3}\)的分都是最高的。T1逆......