链表 oj2 (7.31)

news2024/11/19 3:42:26

206. 反转链表 - 力扣(LeetCode)

我们通过头插来实现

将链表上的节点取下来(取的时候需要记录下一个节点),形成新的链表,对新的链表进行头插。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head)
{
       //用cur对原链表进行遍历
       struct ListNode* cur=head,*newhead=NULL;
       //原链表为空,遍历结束
       while(cur)
       {
       //记录cur的下一个节点
       struct ListNode* next=cur->next;
       //cur链接到新链表
       cur->next=newhead;
       //cur成为新链表的头指针
       newhead=cur;
       //cur通过next在原链表中向后移
       cur=next;
       }
       return newhead;
}

21. 合并两个有序链表 - 力扣(LeetCode)

这里需要引用哨兵位,先介绍一下

    

哨兵位就是不带数据的头节点,且为固定的节点,当链表为空时,带哨兵位的链表(右)存在一个头节点(空间),而不带哨兵位的链表(左)则没有节点。

更改带哨兵位的链表(增删查改)就不需要判断,通过二重指针改变头指针,通过 next 就能直接实现。

使用的时候为哨兵位申请一块动态内存,作为头节点,结束的时候可以根据题目要求将其释放。

实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    if(list1==NULL)
    {
        return list2;
    }
    if(list2==NULL)
    {
        return list1;
    }
       struct ListNode* head=NULL,*tail=NULL;
       //带一个哨兵位,方便尾插
       head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));
       while(list1&&list2)
       {
       if(list1->val<list2->val)
       {
               tail->next=list1;
               tail=tail->next;
               list1=list1->next;
       }
       else
       {
               tail->next=list2;
               tail=tail->next;
               list2=list2->next;
       }
       }
       //
       if(list2)
       {
           tail->next=list2;
       }
       if(list1)
       {
           tail->next=list1;
       }
       //哨兵位的头使用完需要释放掉
       struct ListNode* del=head;
       head=head->next;
       free(del);

       return head;
}

链表分割_牛客题霸_牛客网 (nowcoder.com)

思路是创建两个链表,将小于 x 的尾插到第一个链表,大于 x 尾插到第二个链表。

此题目用带哨兵位的链表做更加简单,因为尾插时不用考虑链表是否为空的情况,将两个链表链接的时候也不需要考虑其中一个链表为空的情况了(即不用担心链表为空的情况)。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
#include <cstddef>
class Partition {
  public:
    ListNode* partition(ListNode* pHead, int x) {
        struct ListNode* ghead, *gtail, *lhead, *ltail;
        ghead = gtail = (struct ListNode*)malloc(sizeof(struct ListNode));
        lhead = ltail = (struct ListNode*)malloc(sizeof(struct ListNode));
        //用cur遍历
        struct ListNode* cur = pHead;
        while (cur)
        {
        if(cur->val < x)
        {
           ltail->next = cur;
           ltail = ltail->next;
        }
            else
            {
            gtail->next = cur;
            gtail = gtail->next;
            }
            cur = cur->next;
            
        }
        //将低链表的尾链接到高链表的哨兵位之后的节点
        ltail->next = ghead->next;
        //将目标链表的尾置空,否则产生环
        gtail->next = nullptr;
        //拷贝目标链表的头节点
        struct ListNode* head = lhead->next;
        //释放哨兵位
        free(lhead);
        free(ghead);
        return head;
    }
};

链表的回文结构_牛客题霸_牛客网 (nowcoder.com)

回文结构就是对称的意思,例如 1 2 2 1,1 2 3 2 1。

结合前面的 oj 题目,我们容易想到一个方法,先找出链表的后半段,然后将其逆置,再将其与前半段比较,如果都相同,则为回文结构。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    //反转链表
    struct ListNode* reverseList(struct ListNode* head)
{
       //用cur对原链表进行遍历
       struct ListNode* cur=head,*newhead=nullptr;
       //原链表为空,遍历结束
       while(cur)
       {
       //记录cur的下一个节点
       struct ListNode* next=cur->next;
       //cur链接到新链表
       cur->next=newhead;
       //cur成为新链表的头指针
       newhead=cur;
       //cur通过next在原链表中向后移
       cur=next;
       }
       return newhead;
}
    //找出中间节点
    struct ListNode* middleNode(struct ListNode* head){
      struct ListNode* slow=head,*fast=head;
      while(fast&&fast->next)
      {
            slow=slow->next;
            fast=fast->next->next;
      }
      return slow;
}
    bool chkPalindrome(ListNode* head) {
        //找出后半段
        struct ListNode* mid=middleNode(head);
        //将后半段逆置
        struct ListNode* rmid=reverseList(mid);
        while(rmid&&head)
        {
            if(rmid->val!=head->val)
            {
                return false;
            }
            rmid=rmid->next;
            head=head->next;
        }
        return true;
    }
};

160. 相交链表 - 力扣(LeetCode)

思路:

1.遍历计算出A,B链表各自的长度 lenA,lenB

2.长的链表走差距步 lenA-lenB,此时两条链表的长度相同

3.同时移动找交点(指针相同),最后返回这个交点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* curA=headA,*curB=headB;
    int lenA=1,lenB=1;
    //提示了链表不为空,因此结尾用下一个节点判断,同时初始长度为1
    while(curA->next)
    {
        curA=curA->next;
        lenA++;
    }
    while(curB->next)
    {
        curB=curB->next;
        lenB++;
    }
    //尾节点不同,一定没有交点
    if(curA !=curB)
    {
        return NULL;
    }
     struct ListNode* longList=headA,*shortList=headB;
     if(lenA<lenB)
     {
        longList=headB;
        shortList=headA;
     }
     //算出差距步(绝对值)
     int gap=abs(lenA-lenB);
     //长的先走差距步
     while(gap--)
     {
         longList=longList->next;
     }
     //同时走找交点,相等就找到了
     while(longList !=shortList)
     {
          longList=longList->next;
          shortList=shortList->next;
     }
     return longList;
}

141. 环形链表 - 力扣(LeetCode)

链表有循环或者非循环

循环链表的尾节点指向头节点。

还有一种带环链表,它的尾节点可以指向链表的任意一个节点(包括自己)。

带环链表中的节点会重复出现,我们依然定义一快一慢指针,如果是带环链表,那么快指针一定能追上慢指针,两个指针一定有相等的时候(追及问题);如果不带环,直接就遍历到空了。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
     struct ListNode* fast=head,*slow=head;
     //链表可能不为环形
     while(fast&&fast->next)
     {
         fast=fast->next->next;
         slow=slow->next;
         if(slow==fast)
         {
             return true;
         }
     }
     return false;
}

由带环追及问题引发的思考:

1.slow走一步,fast走两步,一定能追上吗,会不会错过?

2.slow走一步,fast走n步(n>=3),一定能追上吗,会不会错过?

如果 slow 走一步,fast 走三步,假设 slow 入环时,slow 和 fast 的距离为 M,每移动(追击)一次,距离缩小2,若 M 为偶数,则当距离减为0时,刚好追上;若 M 为奇数,距离最小时为 -1,即fast 超过了 slow 一步,此时又要观察环的长度C,此时 slow 和 fast 的距离为 C-1,若 C 为奇数,C-1为偶数,那么再经过一轮追击之后就能刚好追上。如果 C 为偶数,那么 C-1 为奇数,奇数-2 永远为奇数,就永远追不上了。 

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

分析:

设七点到入口长度:L

环的周长:C

入口点到相遇点的距离:X

fast 走的距离(速度)为 slow 的二倍

slow 进环后的一圈内,fast 一定追上 slow,slow 走的距离为 L+X

slow 进环时,fast 已经走了 n(n>=1) 圈了,fast 走的距离为 L+n*C+X

fast 追赶 slow 之前会先补足 n 圈,

fast 走的距离(速度)为 slow 的二倍可知

2(L+X)=L+n*C+X

同减去L+X

L+X=n*C

L=n*C-X

计算的时候我们默认为 fast 已经跑到 n-1 圈,因此不需要关注 n .

从这个结论我们可以得到从相遇点到环入口点的距离从起点到入口点的距离相同,要想找到入口点,就需要两个指针分别从这两个点开始跑,它们相遇的位置就是入口点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast,*slow;
    fast=slow=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        //相遇
        if(slow==fast)
        {
            //记录相遇点
            struct ListNode* meet=slow;
            //各自从相遇点和头节点开始跑,相遇则为入口点
            while(head!=meet)
            {
                head=head->next;
                meet=meet->next;
            }
            return meet;
        }
    }
    //fast或fast的下一个节点为空,说明无环
    return NULL;
}

法2:

将环从相遇点断开,相遇点之后作为一条新的链表,和旧链表一起找相交点,相交点就是入口点。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年湖北建筑安全员abc三类人员考试新题库考试题库

2024年湖北建筑安全员abc三类人员考试新题库考试题库 湖北三类人员建筑安全员ABC证新题库是存在的&#xff0c;因为安管系统老更新&#xff0c;每次更新后&#xff0c;新题库&#xff08;重点题库&#xff09;就会有所变化。新题库主要是针对考试的&#xff0c;提高考试合格率…

基于selenium的pyse自动化测试框架

介绍&#xff1a; pyse基于selenium&#xff08;webdriver&#xff09;进行了简单的二次封装&#xff0c;比selenium所提供的方法操作更简洁。 特点&#xff1a; 默认使用CSS定位&#xff0c;同时支持多种定位方法&#xff08;id\name\class\link_text\xpath\css&#xff09;…

新工控机的基本配置过程

我们50水球上的工控机使用的是&#xff1a;英特尔 NUC10i7FNH 迷你电脑&#xff08;通过查看铭牌获知&#xff09;。对应官网&#xff1a; https://www.intel.cn/content/www/cn/zh/support/products/188811/intel-nuc/intel-nuc-kits/intel-nuc-kit-with-10th-generation-inte…

【temu】分析拼多多跨境电商Temu数据分析数据采集

Temu是拼多多旗下跨境电商平台&#xff0c;于2022年9月1日在美国、加拿大、新加坡、中国台湾、中国香港等市场上线。本文作者从销售额、销量、产品分布等方面&#xff0c;对Temu产品进行了分析&#xff0c;一起来看一下吧。 item_get获得商品详情item_review获得商品评论列表it…

线上购药小程序的崭新时代:医疗与科技的完美结合

在当今数字化时代&#xff0c;医疗和科技的融合已经催生了许多创新的解决方案&#xff0c;其中线上购药小程序正是医疗与科技完美结合的杰出代表。在这篇文章中&#xff0c;我们将一起探讨如何使用现代技术来创建一个简单的线上购药小程序原型&#xff0c;以展示医疗和科技的崭…

Mysql 约束,基本查询,复合查询与函数

文章目录 约束空属性约束默认值约束zerofill主键约束自增长约束唯一键约束外键约束 查询select的执行顺序单表查询排序 updatedelete整张表的拷贝复合语句group by分组查询 函数日期函数字符串函数数学函数其他函数 复合查询合并查询union 约束 空属性约束 两个值&#xff1a…

springcloud之项目实战服务治理

写在前面 在这篇文章 我们已经搭建完成了优惠券模块的单体版本&#xff0c;为了向微服务化迈出坚实的一步&#xff0c;这部分来看下服务治理的内容&#xff0c;并在我们的项目中引入服务治理&#xff0c;下面我们就开始吧&#xff01; 源码 。 1&#xff1a;什么是&#xff…

基于Java公益志愿捐赠管理系统设计与实现(源码+LW+调试+开题报告)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

卡尔曼滤波器融合六轴IMU数据

卡尔曼滤波 卡尔曼滤波是一种常用的状态估计方法&#xff0c;其基本原理是对系统状态进行最优估计。其主要思想是将系统的状态分为先验状态和后验状态&#xff0c;通过将先验状态和观测值进行加权平均&#xff0c;得到最优估计状态。 卡尔曼滤波增益的计算是使后验误差协方差…

程序员工作5年,还是个中级程序员,如何再快速晋升?

我曾经就是这个状态&#xff0c;5年工作经验就像是一年工作经验用了5年。职业生涯遇到了瓶颈&#xff0c;无法突破。分析原因有很多&#xff0c;一方面是基本功没练好&#xff0c;像操作系统底层、数据结构、算法、计算机网络这些计算机基础知识掌握的不扎实&#xff0c;不能灵…

vue项目的创建——总结版

目录 前提&#xff1a; 一、vue项目的创建 二、浏览项目页面 三、vue项目目录文件含义和作用 ​四、修改端口号 前提&#xff1a; 首先要有Node.js环境。 1.安装vue npm install vue 2.命令行工具&#xff08;CLI&#xff09;为单页面应用快速搭建繁杂的脚手架 npm in…

vulnhub之MATRIX-BREAKOUT 2 MORPHEUS

信息收集 输入命令&#xff1a;arp-scan 192.168.239.0/24&#xff0c;探测存活主机&#xff0c;发现192.168.239.185 对存活主机进行端口扫描&#xff0c;发现&#xff1a;22、80、81端口 浏览器访问http://192.168.239.185:81是一个登录界面 浏览器访问http://192.168.239.…

大模型携手AI原生应用融入产业场景

前言 10月17日&#xff0c;百度世界2023在北京首钢园召开。百度集团执行副总裁、百度智能云事业群总裁沈抖宣布&#xff0c;对“云智一体”的战略内涵全面升级&#xff0c;即云智一体&#xff0c;深入产业&#xff0c;生态繁荣&#xff0c;AI普惠。重磅发布“千帆AI原生应用开…

ASO优化之增加APP应用下载安装量的技巧1

想要增加APP应用的下载安装量&#xff0c;首先要在发布之前&#xff0c;分析我们的应用推广策略该如何运作并进行调整。提高知名度的基础是关键词&#xff0c;其次使用社交网络来推广我们的应用程序。 1、基础与规划。 在启动应用程序或者是实行ASO计划之前&#xff0c;需要了…

6-3 用链栈实现将非负的十进制数转换为指定的进制数【有题解视频,可本地编译器调试】 分数 15

int DecimalConvert(LinkStack s, int dec, int scale) {while (dec){if (LinkStackPush(s, dec % scale))dec dec / scale;elsereturn 0;}return 1; }

微信小程序获取手机号和openid

小程序通过wx.login组件会返回一个code&#xff0c;这个code用来获得用户的openid。 小程序写法为&#xff1a; wx.login({success (res) {if (res.code) {//发起网络请求wx.request({url: https://example.com/onLogin,// 后台给的请求地址data: {code: res.code}})} else {…

流程图如何制作?好用的11款流程图软件盘点!

流程图是一种强大的可视化工具&#xff0c;用于清晰地展示各种过程和步骤&#xff0c;应用非常广泛&#xff0c;在各个行业中随处可见&#xff0c;凡是涉及流程步骤的场景&#xff0c;都可以用到流程图&#xff0c;那么问题来了&#xff1a;流程图如何制作&#xff1f; 这篇文…

性能优化-卡顿优化-tarce抓取及分析

性能优化&#xff08;卡顿分析&#xff09; 文章目录 一、抓取trace的方法1.使用systrace抓取trace2.使用atrace抓取3.使用Perfetto抓取trace 二、trace文件的分析1.快捷操作1.1 导航操作1.2 快捷操作 2.chrome trace工具分析trace文件3.Prefetto分析trace文件 一、抓取trace的…

C++初阶-类和对象(上)

类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装访问限定符封装 五、类的作用域六、类的实例化七、类的对象大小的计算如何计算类对象的大小类对象的存储方式猜测 八、类成员函数的this指针this指针的引出…

精神科常用评估量表汇总,建议收藏!

根据精神科医生的量表使用情况&#xff0c;笔者整理了10个精神科常用量表&#xff0c;可在线评测直接出结果&#xff0c;可转发使用&#xff0c;可生成二维码使用&#xff0c;可创建项目进行数据管理&#xff0c;有需要的小伙伴赶紧收藏&#xff01; 抑郁自评量表 抑郁自评量表…