首页 > 其他分享 >两两交换链表中的节点、删除链表倒数第N个结点、链表相交、环形链表

两两交换链表中的节点、删除链表倒数第N个结点、链表相交、环形链表

时间:2023-09-24 22:36:35浏览次数:48  
标签:结点 slow ListNode cur next 链表 倒数第 指针

题目要求

LeetCode24两两交换链表中的节点
LeetCode19删除链表的倒数第N个结点
LeetCode面试题02.07链表相交
LeetCode142环形链表II

题目思路

24两两交换链表中的节点

  本题采用具有虚拟头结点的链表来写,卡哥的示意图如下:
image
image
image
  首先要交换的两个链表的前一个结点,然后修改指针,注意指针修改顺序,在修改的时候要时刻注意所修改的指针的后继能不能找到,如果修改之后找不到并且后续操作还需要用到这个后继,那就要把这个后继记录下来,带有虚拟头结点循环结束的条件是cur->next或cur->next->next==NULL,cur不可能为NULL,因为cur每次指向的是交换后的两个节点的第二个。
  本题的源代码如下

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *vhead=new ListNode(0);
        vhead->next=head;
        ListNode *cur=vhead;
        while(cur->next!=NULL&&cur->next->next!=NULL)
        {
            ListNode *temp1=cur->next;
            cur->next=cur->next->next;
            ListNode *temp2=cur->next->next;
            cur->next->next=temp1;
            cur->next->next->next=temp2;
            cur=cur->next->next;
        }
        return vhead->next;

    }
};

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

  我拿到这道题的本能反应还是暴力破解,思路是,通过一次循环记录下一共有多少结点,再经过一次循环找到倒数第n个结点的前驱结点,然后进行删除操作

BUT!!!

  这题还可以使用双指针法,思路是设置一个快指针和一个慢指针,快指针比慢指针要快n+1步,这样当快指针指向NULL的时候,慢指针正好指向倒数第n个结点的前驱。
  双指针法是真的很妙,回想这个为什么可以用双指针法,以及之前做过的题,我发现,这种可以找到快慢指针关系的,用双指针法再合适不过了,只是这层关系比较难想,就比如我第一反应不会想到,快指针最终指向NULL这个关系。
  注意:本题代码实现让快指针先多走一步,然后再用n的关系进行while循环,实现多走n+1步的目的,这个多走一步最好放到循环前,因为如果n太大,快指针可能循环后为空,本题源代码如下:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *vhead=new ListNode(0,head);
        ListNode *slow=vhead;
        ListNode *qucik=slow->next;
        //不要把多走一步的操作放到slow后面,因为快指针可能为空
        while(n&&qucik!=NULL)
        {
            qucik=qucik->next;
            n--;
        }
        while(qucik!=NULL)
        {
            slow=slow->next;
            qucik=qucik->next;
        }
        ListNode *temp=slow->next;
        slow->next=slow->next->next;
        delete temp;
        return vhead->next;

    }
};

面试题02.07 链表相交

  拿到这题我的第一反应仍然是暴力破解,第二反应是,把链表逆置过来,从后往前检查,我当时还觉得自己贼聪明,终于想到了一个不是暴力破解的方法,结果实践起来写了很多代码,然而,由于太复杂并且不断改变链表结构,最后也没写出来!
  这题卡哥的思路是,首先计算两个链表的长度,num=长的-短的,让长的从num开始,与短的逐一比对,当两个指针相等的时候,就返回这个指针,即为两个链表相交的结点。
  这里要特别注意,链表相交不代表数值相同。本题源代码如下:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int i=0,j=0;
        ListNode *curA=headA;
        ListNode *curB=headB;
        while(curA!=NULL)
        {
            i++;
            curA=curA->next;
        }
        while(curB!=NULL)
        {
            j++;
            curB=curB->next;
        }
        curA=headA;
        curB=headB;
        //让A是比较长的那个
        if(i<j)
        {
            swap(i,j);
            swap(curA,curB);
        }
        int num=i-j;
        //往后挪动num步
        while(num--)
        curA=curA->next;
        while(curA!=curB&&curA!=NULL)
        {
            curA=curA->next;
            curB=curB->next;
        }
        //这里不用再分情况讨论,如果没有相交的结点,返回curA也是返回NULL
        return curA;
    }

142环形链表II

  这题给人一种要长脑子的感觉……推导很复杂,我也有点讲不明白,还是看代码随想录环形链表

lass Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow=head;
        ListNode *quick=head;
        int i=0;
        //要判断空链表
        if(head==NULL)
        return NULL;
        while(quick->next!=nullptr&&quick->next->next!=nullptr)
        {
            quick=quick->next->next;
            slow=slow->next;
            i++;
            if(slow==quick)
            break;
        }
        if(quick->next==nullptr||quick->next->next==nullptr)
        return NULL;
        else
        {
            quick=head;
            {
                while(slow!=quick)
                {
                    slow=slow->next;
                    quick=quick->next;

                }
                return slow;
            }
        }

    }
};

总结反思

  我觉得可能需要在写算法题的时候想想为什么可以这样想,以后遇到哪种情况也可以这样想.
  总归是坚持下来了,也总归是有一点点暴力破解之外的想法了,尽管想法还是有点复杂,加油加油,会越来越好的!

标签:结点,slow,ListNode,cur,next,链表,倒数第,指针
From: https://www.cnblogs.com/hellozznx/p/17726733.html

相关文章

  • 算法打卡|Day4 链表part02
    Day4链表part02今日任务●24.两两交换链表中的节点●19.删除链表的倒数第N个节点●面试题02.07.链表相交●142.环形链表II[TOC]Problem:24.两两交换链表中的节点思路1.迭代法就要注意画图!画图!还是画图!另外迭代的次序不要忘记,链表迭代统一从左往右迭代。用三......
  • 力扣-链表组件
    1.问题给定链表头结点head,该链表上的每个结点都有一个唯一的整型值。同时给定列表G,该列表是上述链表中整型值的一个子集。返回列表G中组件的个数,这里对组件的定义为:链表中一段极长连续结点的值(该值必须在列表G中)构成的集合。极长的含义是:这段连续结点的前面或后面结点不......
  • 算法打卡|Day3 链表part01
    Day3链表part01今日任务●链表理论基础●203.移除链表元素●707.设计链表●206.反转链表[TOC]链表理论基础文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html重点:单链表是一种通过指针串联在一起的线性结构,每一......
  • Leetcode刷题21.合并两个有序链表
    将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0] 提示:两个链表的节点数目......
  • 随想录Day4|24. 两两交换链表中的节点、19. 删除链表的倒数第N个节点、面试题 02.07.
    随想录Day4|24.两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题02.07.链表相交、142.环形链表Ⅱ 24.两两交换链表中的节点文章讲解视频讲解给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,......
  • 【算法】链表
    1链表理论基础链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。链表的入口节点称为链表的头结点也就是head。链表中的节点在内存中不是连续分布的,而是散乱分布在内......
  • 数据结构之 - 链表数据结构详解: 从基础到实现
    链表(LinkedList)是计算机科学中常用的数据结构之一,它具有灵活的内存分配和高效的插入、删除操作。本文将深入介绍链表的特性、基本类型、操作以及在实际应用中的使用场景。1.什么是链表?链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的引用(或指针)。与数......
  • LeetCode3题学透链表初始化、查找、插入删除、逆置操作
    1.题目要求LeetCode203移除链表指定元素LeetCode707设计链表LeetCode206反转链表  这三个题目包含了链表的初始化、插入头尾结点、插入删除第n个结点,删除指定内容的结点、链表的逆置等,下面我将一一讲解并展示源代码。2.具体操作2.1LeetCode中链表的初始化  我下面所讲......
  • 线性表之单链表(下)
    话不多说,只要写了几个线性表的操作,其中包括:表的反转,表的相邻节点间data的最大值,以及2个链表按照顺序大小合并//头文件:link_list.htypedefintdata_t;typedefstructnode{data_tdata;structnode*next;}listnode,*linklist;//倒置链表intlist_reverse......
  • 创建单个结点
    1.创建单个结点SLTNode*BuySLTNode(SLTDataTypex){ SLTNode*newnode=(SLTNode*)malloc(sizeof(SLTNode));//申请空间 if(newnode==NULL)//判断是否为空 { perror("BuySLTNodemalloc"); exit(-1); } newnode->val=x;//赋值 newnode->next=NULL;//next指针......