首页 > 编程语言 >代码随想录算法训联营第四天|LeetCode24. 两两交换链表中的节点 LeetCode19.删除链表的倒数第N个节点 面试题02.07. 链表相交 LeetC142.环形链表II

代码随想录算法训联营第四天|LeetCode24. 两两交换链表中的节点 LeetCode19.删除链表的倒数第N个节点 面试题02.07. 链表相交 LeetC142.环形链表II

时间:2024-07-08 17:28:00浏览次数:19  
标签:head ListNode 随想录 next 链表 NULL 节点

系列文章目录

代码随想录算法训练营第四天:代码随想录|LeetCode24. 两两交换链表中的节点 LeetCode19.删除链表的倒数第N个节点 面试题02.07. 链表相交 LeetC142.环形链表


文章目录


前言

代码随想录|LeetCode24. 两两交换链表中的节点 LeetCode19.删除链表的倒数第N个节点 面试题02.07. 链表相交 LeetC142.环形链表II
文章链接


一、LeetCode24. 两两交换链表中的节点

1、题目链接

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

2、题解

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* cur = head;
        if (cur == NULL)
            return head;
        if (cur->next == NULL)
            return head;
        if (cur->next->next == NULL) {
            ListNode* t1 = head;
            ListNode* t2 = head->next;
            ListNode* t3 = head->next->next;
            head = t2;
            head->next = t1;
            head->next->next = t3;
            cur = t1;
            return head;
        }
        while (cur->next != NULL && cur->next->next != NULL) {
            if (cur == head) {
                ListNode* t1 = head;
                ListNode* t2 = head->next;
                ListNode* t3 = head->next->next;
                head = t2;
                head->next = t1;
                head->next->next = t3;
                cur = t1;
            } else {
                ListNode* temp = cur->next;
                ListNode* k = cur->next->next->next;
                cur->next = cur->next->next;
                cur->next->next = temp;
                cur->next->next->next = k;
                cur = cur->next->next;
            }
        }
        return head;
    }
};

二、LeetCode19.删除链表的倒数第N个节点

1.题目链接

LeetCode19.删除链表的倒数第N个节点
这道题定位是要点

2.暴力法

(1)思路:
先从头到尾遍历,求出长度,再用长度和n定位
(2)C语言题解

int getlen(struct ListNode* head)
{
    int res=0;
    if(head==NULL)return res;
    struct ListNode* p=head;
    while(p!=NULL)
    {
        res++;
        p=p->next;
    }
    return res;
}
void delete(struct ListNode * head,int m)
{
    struct ListNode* now=head;
    struct ListNode* pre=(struct ListNode*)malloc(sizeof(struct ListNode));
    pre->next=head;
    
    int i=1;
    for(i;i<m;i++)
    {
        pre=now;
        now=now->next;
    }
    
    pre->next=now->next;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    if(head==NULL)return head;
    int l=getlen(head);
    struct ListNode* now=head;
    struct ListNode* pre=(struct ListNode*)malloc(sizeof(struct ListNode));
    pre->next=head;
    if(l==n)
    {
        head=head->next;
    }
    for(int i=1;i<l-n+1;i++)
    {
        pre=now;
        now=now->next;
    }
    pre->next=now->next;
    return head;
}

该处使用的url网络请求的数据。

3、仅遍历一次的做法:快慢指针

(神奇的是暴力法的用时更短)
(1)思路
1)既然要删除倒数第n个节点,那么我们需要把慢指针p放在倒数第n个节点的前一个节点处(n+1),那么如何确定何时到达这个位置呢
2)我们再用一个快指针,当快指针为最后一个节点时,快指针应当领先于慢指针n个节点
3)所以一开始让快指针先走n个节点,再让两个指针同时前进,直到快指针的下一个节点为空,即快指针到达最后一个节点
4)这时候慢指针为倒数n+1个节点
(2)题解

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy= new ListNode(0,head);
        ListNode* p=dummy;
        ListNode* end=dummy;
        for(int i=0;i<n;i++)
        {
            if(end->next==NULL)break;
            end=end->next;
        }
        while(end!=NULL && end->next!=NULL)
        {
            end=end->next;
            p=p->next;
        }
        p->next=p->next->next;
        return dummy->next;
    }
};

三、面试题02.07. 链表相交

1、题目链接

面试题02.07. 链表相交

2、思路

(1)这里注意链表相交不是值相等,而是地址相等
(2)如果链表相交,那么从相交点以后的长度也相等。链表的终点都是NULL,在思考的时候,可以将链表尾部对齐
(3)如果两个链表长度不同,那么长的链表多出来的部分是不可能相交的,所以先把长的链表遍历的指针移动到和短链表平齐的位置
(4)接下来同时移动两个指针,如果地址相同,则为相交点,返回此时的指针

3、题解

class Solution {
public:
    int len(ListNode* head) {
        ListNode* p = head;
        int ans = 0;
        while (p != NULL) {
            p = p->next;
            ans++;
        }
        return ans;
    }
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* ans = NULL;
        ListNode* p1 = headA;
        ListNode* p2 = headB;
        int lenA = len(headA);
        int lenB = len(headB);
        if (lenA > lenB) {
            int n = lenA - lenB;
            for (int i = 0; i < n; i++) {
                p1 = p1->next;
            }
        } else if (lenA < lenB) {
            int n = lenB - lenA;
            for (int i = 0; i < n; i++) {
                p2 = p2->next;
            }
        }
        while (p1 != NULL && p2 != NULL) {
            if (p1 == p2) {
                ans = p1;
                break;
            }
            p1 = p1->next;
            p2 = p2->next;
        }

        return ans;
    }
};

四、LeetC142.环形链表II

1、题目链接

LeetC142.环形链表II

2、思路

(1)判断是否有环
快慢指针fast和slow,fast每次移动两个,slow每次移动一个
二者相遇则有环
(2)判断环的入口
再设两个指针p1,p2分别从头结点和快慢指针相遇点出发,每次移动一个,二者相遇点为入口
推导
示意图
示意图
fast和slow相遇时,假设slow第一次进入环,fast在环中多转n圈,此时fast走过的路程是x+y+n(y+z),等于slow路程的二倍,x+y+n(y+z)=2(x+y)
所以x=z+(n-1)(y+z) (1)
在环入口处,从head出发走了x,从快慢节点相遇点出发走了z+(n-1)(y+z)【(n-1)(y+z)是转圈的路程】,由于同时出发和式(1),当p1p2二者相遇的时候是环的入口

注意:先移动,再比较是快慢指针否相等,因为快慢指针的起点都是head

3、题解

class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode*  pos=NULL;
        while (fast != NULL && fast->next != NULL) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                ListNode* p1 = head;
                ListNode* p2 = fast;
                while (p1 != p2) {
                    p1 = p1->next;
                    p2 = p2->next;
                }
                pos=p1;
                break;
            }
            
        }
        return pos;
    }
};

总结

链表部分知识点
1、链表理论知识
2、虚拟头结点的技巧
3、链表的增删改查
4、反转一个链表
5、删除倒数第N个节点
6、链表相交
7、有否环形,以及环的入口

标签:head,ListNode,随想录,next,链表,NULL,节点
From: https://blog.csdn.net/2301_79647020/article/details/140248144

相关文章

  • 「代码随想录算法训练营」第五天 | 哈希表 part1
    242.有效的字母异位词题目链接:https://leetcode.cn/problems/valid-anagram/题目难度:简单文章讲解:https://programmercarl.com/0242.有效的字母异位词.html视频讲解:https://www.bilibili.com/video/BV1YG411p7BA题目状态:一次过,哈哈哈个人思路:之前在《剑指offer》中做过......
  • 代码随想录算法训练营第25天 | 491.递增子序列
    491.递增子序列给定一个整型数组,你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。示例:输入:[4,6,7,7]输出:[[4,6],[4,7],[4,6,7],[4,6,7,7],[6,7],[6,7,7],[7,7],[4,7,7]]说明:给定数组的长度不会超过15。数组中的整数范围是[-10......
  • 单链表在Python中的实现技巧详解
    概要链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。链表的优点是插入和删除操作非常高效,特别是在需要频繁修改数据结构的情况下。本文将详细介绍如何在Python中创建单链表,并包含相应的示例代码,帮助全面掌握这一基础而重要......
  • 代码随想录算法训练营第56天 | 42. 接雨水 、84.柱状图中最大的矩形
    图论理论基础大家可以在看图论理论基础的时候,很多内容看不懂,例如也不知道看完之后还是不知道邻接矩阵,邻接表怎么用,别着急。理论基础大家先对各个概念有个印象就好,后面在刷题的过程中,每个知识点都会得到巩固。https://www.programmercarl.com/kamacoder/图论理论基础.html......
  • 【后端面试题】【中间件】【NoSQL】MongoDB提高可用性的方案(主从结构、仲裁节点、分片
    主从结构MongoDB的高可用和别的中间件的高可用方案基本类似。比如在MySQL里,接触了分库分表和主从同步;在Redis里,Redis也有主从结构;在Kafka里,分区也是有主从结构的。所以先介绍启用了主从同步我们的系统有一个关键组件-MongoDB,但是在最开始的时候,MongoDB没有启用主从,是......
  • 代码随想录算法训练营第55天 | 42. 接雨水 、84.柱状图中最大的矩形
    接雨水接雨水这道题目是面试中特别高频的一道题,也是单调栈应用的题目,大家好好做做。建议是掌握双指针和单调栈,因为在面试中写出单调栈可能有点难度,但双指针思路更直接一些。在时间紧张的情况有,能写出双指针法也是不错的,然后可以和面试官在慢慢讨论如何优化。https://p......
  • 双向链表模拟
    LinkedList底层结构LinkedList底层实现了双向列表和双端队列的特点可以添加任意元素可重复,包括null线程不安全,为实现线程同步底层操作机制LinkedList底层维护了一个双向链表。LinkedList中维护了两个属性first和last分别指向首节点和尾节点每个节点对象(Node对象),里面又维......
  • ComfyUI进阶篇:ComfyUI核心节点(三)
    ComfyUI核心节点(三)前言:学习ComfyUI是一场持久战。当你掌握了ComfyUI的安装和运行之后,会发现大量五花八门的节点。面对各种各样的工作流和复杂的节点种类,可能会让人感到不知所措。在这篇文章中,我们将用通俗易懂的语言对ComfyUI的核心节点进行系统梳理,并详细解释每个参数。希望大家......
  • 【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统
    不同类型的链表​专栏内容:postgresql使用入门基础手写数据库toadb并发编程个人主页:我的主页管理社区:开源数据库座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.文章目录不同类型的链表概述1.数据类型识别1.1TLV格式介绍1.2结构体分层定义1.3定义......
  • 环形链表II
    给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。如果......