【数据结构】——链表经典OJ(leetcode)

文章目录

  • 一、 相交链表
  • 二、 反转链表
  • 三、 回文链表
  • 四、 环形链表
  • 五、 环形链表 II
  • 六、 合并两个有序链表
  • 七、 两数相加
  • 八、 删除链表的倒数第N个节点
  • 九、 随机链表的复制

一、 相交链表

在这里插入图片描述
双指针法

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* curA = headA;
    struct ListNode* curB = headB;
    int lenA = 1,lenB = 1;
    while(curA->next)
    {
        curA = curA->next;
        lenA++;
    }
    while(curB->next)
    {
        curB = curB->next;
        lenB++;
    }
    //终点相同才能进行下一步
    if(curB != curA)
    {
        return NULL;
    }
    //假设法
    //长的先走
    int gap = abs(lenA - lenB);
    struct ListNode* longlist = headA;
    struct ListNode* shortlist = headB;
    if(lenB>lenA)
    {
        longlist = headB;
        shortlist = headA;
    }
    while(gap--)
    {
        longlist = longlist->next;
    }
    while(shortlist != longlist)
    {
        shortlist = shortlist->next;
        longlist = longlist->next;
    }
    return shortlist;
}

二、 反转链表

在这里插入图片描述

注意第一个节点的next要为空

 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    if(head == NULL)
    {
        return head;
    }
    ListNode* n1,* n2, *n3;
    n1 = NULL;
    n2 = head;
    n3 = n2->next;
    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
        {
            n3 = n3->next;
        }
    } 
    return n1;

}

三、 回文链表

在这里插入图片描述
这题两个选择,反转前半部分再对比,或者反转后半部分再对比
如果反转前半部分,那么找中间值的条件就为fast->next && fast->next->next不为空,我选择反转后半部分,相对更容易理解
反转的部分参考反转链表

 typedef struct ListNode ListNode;
 ListNode* reverse(ListNode* head)
 {
     if(head == NULL)
    {
        return head;
    }
    ListNode* n1,* n2, *n3;
    n1 = NULL;
    n2 = head;
    n3 = n2->next;
    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
        {
            n3 = n3->next;
        }
    } 
    return n1;
 }
bool isPalindrome(struct ListNode* head) {
    //先找到中间节点
    ListNode* fast = head;
    ListNode* slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    
    //反转后一半节点
    ListNode* p = reverse(slow);
    ListNode* q = head;
    //对比
    while(q != slow)
    {
        if(q->val != p->val)
        return false;
        q = q->next;
        p = p->next;
    }
    return true;
}

四、 环形链表

在这里插入图片描述
快慢指针:用fast先走,等fast进圈后再去追slow

bool hasCycle(struct ListNode *head) {
    typedef struct ListNode ListNode;
    ListNode* slow = head;
    ListNode* fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow)
        {
            return true;
        }
    }
    return false;
}

五、 环形链表 II

在这里插入图片描述
先看代码,这题的代码很简单,但是要明白所以然

 typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* fast = head;
    ListNode* slow = head;;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
        {
            ListNode* meet = slow;
            while(head != meet)
            {
                head = head->next;
                meet = meet->next;
            }
            return head;
        }
    }
    return NULL;
}

在这里插入图片描述
当fast和slow相遇后,我们将meet点设为新的起点,然后head点和meet点往后走,终究会相遇,相遇的点就是环的入口。
在这里插入图片描述

六、 合并两个有序链表

在这里插入图片描述
这题需要注意返回新链表的头节点,所以新链表创建两个节点来记录头和尾节点最方便

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    ListNode* l1 = list1;
    ListNode* l2 = list2;
    //判断链表为空
      if(l1 == NULL)
    {
        return l2;
    }
    if(l2 == NULL)
    {
        return l1;
    }
    //创建新的链表
    ListNode* newhead,* newtail;
    newhead = newtail = (ListNode*)malloc(sizeof(ListNode));
  
    while(l1 && l2)
    {
        if(l1->val < l2->val)
        {   //l1尾插
            newtail->next = l1  ;
            newtail = newtail->next;
            l1 = l1->next;
        }
        else
        {  //l2尾插
            newtail->next = l2;
            newtail = newtail->next;
            l2 = l2->next;
        }
    }//跳出循环后还有两种情况,不是l1走到空,就是l2先走到空
    if(l1)
    {
        newtail->next = l1;
    }
    if(l2)
    {
        newtail->next = l2;
    }
    //手动释放动态内存空间
    ListNode* ret = newhead->next;
    free(newhead);
    newhead = NULL;
    return ret;
}

七、 两数相加

在这里插入图片描述
这题使用递归的方法最好理解

 typedef struct ListNode ListNode;
ListNode* _addTwoNumbers(ListNode* l1,ListNode* l2,int cur)
{
    int sums = cur;
    if(l1 == NULL && l2 == NULL && cur == 0)
    {
        return NULL;
    }
    else{
        if(l1 != NULL)
    {
        sums += l1->val;
        l1 = l1->next;
    }
        if(l2 != NULL)
    {
        sums += l2->val;
        l2 = l2->next;
    }
    }
   
    ListNode* a = (ListNode*)malloc(sizeof(ListNode));
    a->val = sums%10;
    a->next = _addTwoNumbers(l1,l2,sums/10);
    return a;
}
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    return _addTwoNumbers(l1,l2,0);
}

cur为进位值,所以和就为l1->val+l2->val+cur
在这里插入图片描述
判断cur是防止极端情况的发生,例如:
在这里插入图片描述

八、 删除链表的倒数第N个节点

在这里插入图片描述

先记录链表长度,再找到要删除节点的上一个节点

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    int length = 1;
    struct ListNode* p = head;
    struct ListNode* q = head;
    //记录链表长度
    while(p->next)
    {
        p = p->next;
        length++;
    }
    int del = length - n + 1;
    int j = 1;
    //找到要删除节点的上一个节点
    while(j + 1 < del)
    {
        q = q->next;
        j++;
    }
    if(del != 1)
    {
        q->next = q->next->next;
        return head;
    }
    else
    {
        return head = q->next;
    }

}

九、 随机链表的复制

在这里插入图片描述
创建一个copy链表

在这里插入图片描述

在这里插入图片描述
再控制random
在这里插入图片描述
把copy取出尾插为新的链表(恢复原链表)
在这里插入图片描述
源代码:

typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
	Node* cur = head;
    //创建copy链表
    while(cur)
    {
        Node* copy = (Node*)malloc(sizeof(Node));
        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;
        cur = copy->next;
    }
    //完善random 
    cur = head;   
    while(cur)
    {
        Node* copy = cur->next;
        if(cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    //copy取出尾插成为新的链表
    cur = head;
    Node* copyhead = NULL;
    Node* copytail = NULL;
    while(cur)
    {
        Node* copy = cur->next;
        Node* next = copy->next;
        if(copyhead == NULL)
        {
            copyhead = copytail = copy;
        }
        else
        {
            copytail->next = copy;
            copytail = copy;
        }
        //cur->next = next;
        cur = next;
        next = copy->next;
    }
    return copyhead;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/747709.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL进阶-索引-使用规则-最左前缀法则和范围查询

文章目录 1、最左前缀法则2、启动mysql3、查询tb_user4、查看tb_user的索引5、执行计划 profession 软件工程 and age31 and status 06、执行计划 profession 软件工程 and age317、执行计划 profession 软件工程8、执行计划 age31 and status 09、执行计划 status 010、执行…

直流电机双闭环调速Simulink仿真

直流电机参数&#xff1a; 仿真模型算法介绍&#xff1a; 1&#xff09;三相整流桥&#xff0c;采用半控功率器件SCR晶闸管&#xff1b; 2&#xff09;采用转速环、电流环 双闭环控制算法&#xff1b; 3&#xff09;外环-转速环&#xff0c;采用PI 比例积分控制&#xff1b;…

通信系统网络架构_3.移动通信网络架构

移动通信网为移动互联网提供了强有力的支持&#xff0c;尤其是5G网络为个人用户、垂直行业等提供了多样化的服务。以下从业务应用角度给出面向5G网络的组网方式。 1.5GS与DN互连 5GS&#xff08;5G System&#xff09;在为移动终端用户&#xff08;User Equipment&#xff0c;…

搜维尔科技:【研究】触觉手套比控制器更能带来身临其境、更安全、更高效的虚拟体验

自然交互可提高VR模拟的有效性。研究表明&#xff0c;触觉手套比控制器更能带来身临其境、更安全、更高效的虚拟体验。 以下是验证 医疗培训中的触觉技术 “ 95.5%的参与者表示触摸是 XR 教育的重要组成部分&#xff0c;90.9% 的参与者表示 XR 触觉将提供一个安全的学习场所。…

eNSP中ACL访问控制表的配置和使用

一、拓扑图 1.新建拓扑图 2.PC端配置 PC1: PC2: PC3: 二、基本命令配置 1.S1配置 <Huawei>system-view [Huawei]sysname S1 [S1]vlan 10 [S1-vlan10]vlan 20 [S1-vlan20]vlan 30 [S1-vlan30]quit [S1]interface Vlanif 10 [S1-Vlanif10]ip address 192.168.10…

黑马点评06短信登录-用户请求和会话管理过程

用户请求发送&#xff1a; 用户的浏览器向服务器发送请求&#xff08;例如&#xff0c;访问网页或提交表单&#xff09;。请求头包含之前存储在浏览器中的Cookie&#xff0c;其中包括会话ID&#xff08;Session ID&#xff09;。 服务器接收请求&#xff1a; 服务器接收到用户的…

【PythonWeb开发】Flask自定义模板路径和静态资源路径

在大型的 Flask 项目中&#xff0c;确实可能会有多个子应用&#xff08;Blueprints&#xff09;&#xff0c;每个子应用可能都有自己的静态文件和模板。为了更好地管理和组织这些资源&#xff0c;可以使用static_folder 和template_folder 属性来统一管理。必须同时设置好主应用…

利用ChatGPT优化程序员工作流程:实用案例分享

近年来&#xff0c;人工智能技术的迅猛发展给各行各业带来了翻天覆地的变化。作为其中的一员&#xff0c;程序员在工作中也受益匪浅。其中&#xff0c;ChatGPT的出现&#xff0c;更是成为优化程序员工作流程的得力助手。本文将通过多个实用案例&#xff0c;分享如何利用ChatGPT…

鸿蒙系统最简单安装谷歌服务及软件的方法

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 近日&#xff0c;华为开发者大会在东莞松山湖召开&#xff0c;发布了盘古大模型5.0和纯血版的鸿蒙 HarmonyOS NEXT 全场景智能操作系统&#xff0c;而根据研究机构 Counterpoint Resea…

Unity关于Addressables.Release释放资源内存问题

前言 最近在编写基于Addressables的资源管理器&#xff0c;对于资源释放模块配合MemoryProfiler进行了测试&#xff0c;下面总结下测试Addressables.Release的结论。 总结 使用Addressables.Release释放资源时&#xff0c;通过MemoryProfiler检查内存信息发现加载的内容还在…

python-序列相关

序列&#xff08;squence&#xff09;是一组按顺序、紧密排列在一起的数据集。序列的作用是便于管理、方便数据操作更重要的是序列支持切片操作。 序列主要包括&#xff1a;列表、元组、字符串和字节串 内置数据结构&#xff1a; 容器&#xff1a;列表、元组、字典、集合 结构…

CVE-2020-26048(文件上传+SQL注入)

简介 CuppaCMS是一套内容管理系统&#xff08;CMS&#xff09;。 CuppaCMS 2019-11-12之前版本存在安全漏洞&#xff0c;攻击者可利用该漏洞在图像扩展内上传恶意文件&#xff0c;通过使用文件管理器提供的重命名函数的自定义请求&#xff0c;可以将图像扩展修改为PHP&#xf…

苹果笔记本双系统怎么安装

想要在mac电脑上装双系统&#xff0c;首先需要确认您的电脑是否支持。苹果电脑自带的boot camp工具可以帮助您在mac上安装windows系统&#xff0c;只需按照步骤进行操作即可。另外&#xff0c;您也可以使用虚拟机软件&#xff0c;如parallels desktop或vmware fusion&#xff0…

关于Claude3.5-Sonnet引以为傲的功能,在半年前就被某国产平台无情碾压的那档事!

前言&#xff1a; Anthropic声称其每隔几个月就会对Claude发布一次重大版本的更新。距离今年3月份Claude3发布&#xff0c;已经又过去了3个多月的时间。果不其然&#xff0c;6月21日Anthropic 在X上正式官宣发布全新大模型 Claude3.5 Sonnet&#xff0c;号称它能够碾压GPT4o&a…

海思SS928/SD3403开发笔记1——使用串口调试开发板

该板子使用串口可以调试&#xff0c;下面是win11 调试 该板子步骤 1、给板子接入鼠标、键盘、usb转串口 2、下载SecureCRT&#xff0c;并科学使用 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11dIkZVstvHQUhE8uS1YO0Q 提取码&#xff1a;vinv 3、安装c…

导航栏设计的5种类型,新手不容忽视的重要知识!

导航栏是网页设计中不可缺少的一部分。大多数用户在浏览网页时都是从导航栏开始的。导航栏的作用相当于路标和书籍中的目录&#xff0c;其重要性不言而喻。从设计的角度来看&#xff0c;网页导航栏的设计功能大于视觉效果。因此&#xff0c;网页导航栏的设计可以分为 5 类型&am…

STM32启动流程 和 map文件的作用

一&#xff0c;启动流程 1. 复位/上电 2. 根据 BOOT0/BOOT1 确定程序从哪个存储位置执行 3. 初始化 SP 及 PC 指针 将 0X08000000 位置的栈顶地址存放在 SP 指针中 将 0x08000004 位置存放的向量地址装入 PC 程序计数器 4. 初始化系统时钟 5. 初始化用户堆栈 6. 进入main函数 二…

考研数学复习(1/9):函数与极限

目录 函数与极限 1. 函数的概念 1.1 函数的定义 1.2 函数的表示方法 1.3 函数的分类 1.4 函数的运算 2. 极限的概念 2.1 极限的定义 2.2 极限的性质 2.3 极限的计算方法 2.4 极限的应用 3. 连续函数 3.1 连续函数的定义 3.2 连续函数的性质 3.3 连续函数的分类 …

ArcGIS实现不同地块分类与面积汇总

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 我们要做一个不同地块面积汇总&#xff01; 你有一批地块&#xff0c;不同面积&#xff0c;我们需…

python 中面向对象编程:深入理解封装、继承和多态

在本章中&#xff0c;我们将深入探讨Python中的高级面向对象编程概念&#xff0c;包括封装、继承和多态。让我们开始吧&#xff01; 目录 面向对象简介类和实例属性和方法继承和多态 高级面向对象概念私有变量使用 property使用 __slots__类的特殊成员__doc____call____str____…