链表专题1—24. 两两交换链表中的节点 234.回文链表 143.重排链表 141.环形链表 142.环形链表II 160.链表相交 C++实现

news2024/11/19 15:28:00

文章目录

  • 24. 两两交换链表中的节点
  • 234.回文链表
    • 链表转数组+统计长度
    • 反转后半部分链表 快慢指针
  • 143. 重排链表
    • 数组 双指针 超时
    • 双队列
    • 反转和插入链表
  • 141. 环形链表
  • 142.环形链表II
  • 160.链表相交

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

在这里插入图片描述

迭代法,时间复杂度: O ( n ) O(n) O(n), 空间复杂度: O ( 1 ) O(1) O(1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* cur = dummyhead;
        //1->2->3->4
        while(cur->next != nullptr && cur->next->next != nullptr)
        {
            ListNode* temp = cur->next;//保存节点2
            ListNode* temp1 = cur->next->next->next;//保存节点4
            cur->next = cur->next->next;//1->3
            cur->next->next = temp;//3->2
            cur->next->next->next = temp1;//2->4
            //cur移动两位 下一次交换
            cur = cur->next->next;
        }
        return dummyhead->next;
    }
};

234.回文链表

在这里插入图片描述

链表转数组+统计长度

时间复杂度、空间复杂度: O ( n ) O(n) O(n)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //写法1 数组
        /*
        ListNode* cur = head;
        vector<int> result;
        while(cur)
        {
            result.push_back(cur->val);
            cur = cur->next;
        }
        //回文判断 双指针
        for(int i=0, j=result.size()-1; i<j; i++,j--)
        {
            if(result[i] != result[j]) return false;
        }
        return true;*/

        //写法2 统计长度+数组 避免多余空间开辟
        ListNode* cur = head;
        int n = 0;
        while(cur)
        {
            cur = cur->next;
            n++;
        }
        vector<int> result(n);
        cur = head;
        for(int i=0;i<n;i++)
        {
            result[i] = cur->val;
            cur = cur->next;
        }
         for(int i=0, j=result.size()-1; i<j; i++,j--)
        {
            if(result[i] != result[j]) return false;
        }
        return true;
    }
};

反转后半部分链表 快慢指针

  • 止位置时,慢指针就在链表中间位置。
  • 同时用pre记录慢指针指向节点的前一个节点,用来分割链表,将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
  • 将后半部分反转 ,得cur2,前半部分为cur1
  • 按照cur1的长度,一次比较cur1和cur2的节点数值
    时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //写法3 反转后半指针 快慢指针
        if(head == nullptr && head->next == nullptr) return true;
        ListNode* fast = head;//走两步 到终点时 slow在中间位置
        ListNode* slow = head;//走一步 中间位置
        ListNode* pre = head;//记录slow的上一个节点 前半段

        //1.统计位置
        while(fast && fast->next)
        {
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        //2.分割链表
        pre->next = nullptr;
        //3.两段链表 奇数个节点 那么slow在奇数位cur2长度>cur1
        ListNode* cur1 = head;
        ListNode* cur2 = reverseList(slow);
        while(cur1)
        {
            if(cur1->val != cur2->val) return false;
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return true;
    }
    ListNode* reverseList(ListNode* head)
    {
        ListNode* temp = head;
        ListNode* cur = head;
        ListNode* pre = nullptr;
        while(cur)
        {
            //1->2->3 pre->cur->cur.next
            temp = cur->next;//保存节点
            cur->next = pre;//翻转节点
            pre = cur;//更新pre 前移一步  原来cur的上一个节点
            cur = temp;//更新cur 前移一步 原来cur的下一个节点
        }
        return pre;
    }
};

143. 重排链表

在这里插入图片描述

数组 双指针 超时

把链表放进数组中,然后通过双指针法,一前一后,来遍历数组,构造链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        //数组 超时
        //1.节点存入数组
        vector<ListNode*> vec;
        ListNode* cur = head;
        if(cur == nullptr) return;
        while(cur)
        {
            vec.push_back(cur);
            cur = cur->next;
        }
        //2.前后指针 重新排链表
        int i = 1, j = vec.size() - 1;
        int count = 0;//统计奇偶数
        cur = head;
        while(i <= j)
        {
            if(count % 2 == 0)
            {
                cur->next = vec[j];
                i--;
            }
            else
            {
                cur->next = vec[i];
                i++;
            }
            cur = cur->next;
            count++;
        }
        cur->next = nullptr;
    }
};

双队列

把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表。这种方法比操作数组容易一些,不用双指针模拟一前一后了

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        //方法2 两头队列模拟
        ListNode* cur = head;
        deque<ListNode*> que;
        if(cur==nullptr) return;
        while(cur->next != nullptr)
        {
            que.push_back(cur->next);
            cur = cur->next;
        }
        cur = head;
        ListNode* temp;//获取队列节点
        int count = 0;
        while(que.size())
        {
            //偶数获取队列尾部节点
            if(count % 2 == 0)
            {
                temp = que.back();
                que.pop_back();
            }
            else
            {
                temp = que.front();
                que.pop_front();
            }
            cur->next = temp;//连接
            count++;
            cur = cur->next;//cur更新
        }
        cur->next = nullptr;
    }
};

反转和插入链表

将链表分割成两个链表,然后把第二个链表反转,之后在通过两个链表拼接成新的链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        //方法2 链表
        //1.分割链表 快慢指针
        //如果链表长度是奇数 head1长度比head2多一个
        if(head == nullptr) return;
        ListNode* slow = head;//链表后半段的头部 相当于慢指针
        ListNode* fast = head;
        while(fast && fast->next && fast->next->next)
        {
            fast = fast->next->next;slow = slow->next;
        }
        ListNode* head1 = head;//前半部分
        ListNode* head2 = slow->next;//后半部分
        head2 = slow->next;
        slow->next = nullptr;//分割链表

        //2.反转链表
        head2 = reverseList(head2);

        //3.合并链表
        ListNode* cur1 = head1;
        ListNode* cur2 = head2;
        ListNode* cur = head;//合并后链表
        cur1 = cur1->next;//第一次写的时候少了这一行
        int count = 0;
        while(cur1 && cur2)
        {
            //奇数取cur1 偶数取cur2
            if(count % 2 == 0)
            {
                cur->next = cur2;
                cur2 = cur2->next;
            }
            else
            {
                cur->next = cur1;
                cur1 = cur1->next;
            }
            cur = cur->next;
            count++;
        }
        
        //4.结尾处理 先连接偶数再连接奇数节点
        //如果长度是奇数最后一个肯定是奇数节点结尾
         if (cur2 != nullptr) cur->next = cur2;
        if(cur1 != nullptr) cur->next = cur1;
    }
private:
    //反转链表
    ListNode* reverseList(ListNode* head)
    {
        ListNode* temp;
        ListNode* cur = head;
        ListNode* pre = nullptr;
        while(cur)
        {
            temp = cur->next;
            cur->next = pre;//反转
            pre = cur;//先更新pre
            cur = temp;//再更新cur
        }
        return pre;
    }
};

141. 环形链表

在这里插入图片描述
快慢指针,快指针走两步,慢指针走一步, 相遇则说明有环

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        int result = 0;
        if(head == nullptr) return result;
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast) return true;
        }
        return false;
    }
};

142.环形链表II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)//有环 找入口
            {
                ListNode* cur = slow;
                ListNode* entrance = head;
                //不相等一直更新
                while(cur != entrance)
                {
                    cur = cur->next;
                    entrance = entrance->next;
                }
                return entrance;//相等 返回环入口
            }
        }
        return NULL;
    }
};

160.链表相交

面试题 02.07. 链表相交
在这里插入图片描述

两个链表统计长度,保证两个指针在同一个起点同时移动

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
private:
    int countList(ListNode* head)
    {
        int len = 0;
        while(head)
        {
            head = head->next;
            len++;
        }
        return len;
    }
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //1.统计长度
        int lena = countList(headA);
        int lenb = countList(headB);
        //2.让headA为长链表
        if(lena < lenb) swap(headA, headB);
        //3.长链表的节点先移动
        int len = (lena < lenb) ? (lenb - lena) : (lena - lenb);
        ListNode* cura = headA;
        ListNode* curb = headB;
        while(len--)
        {
            cura = cura->next;
        }
        while(cura && curb)
        {
            if(cura == curb) return cura;
            cura = cura->next;
            curb = curb->next;
        }
        return NULL;
    }
};

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

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

相关文章

App store里简单好用的便签app有哪些?

作为一个打工人&#xff0c;我经常需要一个简单而又好用的便签应用来记录我的各种事务和备忘。我曾在App Store里尝试了许多便签应用&#xff0c;但有一款应用真正让我留下了深刻的印象——敬业签。 敬业签的简单和易用性让我爱不释手。无论是添加新的便签&#xff0c;设置提醒…

基础大模型能像人类一样标注数据吗?

自从 ChatGPT 出现以来&#xff0c;我们见证了大语言模型 (LLM) 领域前所未有的发展&#xff0c;尤其是对话类模型&#xff0c;经过微调以后可以根据给出的提示语 (prompt) 来完成相关要求和命令。然而&#xff0c;直到如今我们也无法对比这些大模型的性能&#xff0c;因为缺乏…

为什么程序员更容易抑郁?是因为...

【1】 前段时间&#xff0c;有一位朋友&#xff0c;在后台留言&#xff1a; 《谢谢你听我吐槽&#xff0c;说出来感觉好了很多》 这位程序员朋友在深圳大厂&#xff0c;35岁&#xff0c;10年研发经验&#xff0c;倍感抑郁&#xff0c;吐露了自己的近况&#xff1a; &#xff08…

IDE /skipping incompatible xxx_d.dll when searching for -lxxx_d

文章目录 概述场景复现用以测试的代码编译器位数不匹配导致?保持编译器类型一致再验证编译器位数的影响MingW下调用OS的库咋不告警?以mingW下使用winSocket为例MingW下网络编程的头文件分析该环境下链接的ws2_32库文件在哪里&#xff1f;mingW为啥可以兼容window下的动态库 概…

MySQL自治平台建设的内核原理及实践(下)

总第566篇 2023年 第018篇 本文整理自美团技术沙龙第75期的主题分享《美团数据库攻防演练建设实践》&#xff0c;系超大规模数据库集群保稳系列&#xff08;内含4个议题的PPT及视频&#xff09;的第4篇文章。 本文作者在演讲后根据同学们的反馈&#xff0c;补充了很多技术细节&…

【Web狗自虐系列1】Pwn入门之初级ROP

0x0 栈介绍 栈式一种典型的后进先出的数据结构&#xff0c;其操作主要有压栈(push)与出栈(pop)两种操作 压栈与出栈都是操作的栈顶 高级语言在运行时都会被转换为汇编程序&#xff0c;在汇编程序运行过程中&#xff0c;充分利用了这一数据结构。每个程序在运行时都有虚拟地址…

国产化适配再进一步,融云完成欧拉、TDSQL、优炫等多方适配

近期&#xff0c;融云完成了与开源操作系统欧拉&#xff08;openEuler&#xff09;、企业级数据库 TDSQL 和优炫的适配工作&#xff0c;国产化上下游生态适配之路再次迈进坚实一步。关注【融云 RongCloud】&#xff0c;了解协同办公平台更多干货。 欧拉&#xff08;openEuler&a…

DoTween 学习

部分参考&#xff1a;DOTween中文详解&#xff08;持续更新&#xff09;_一条爱玩游戏的咸鱼的博客-CSDN博客 官方文档&#xff1a;DOTween - Documentation (demigiant.com) 什么是Tween&#xff08;补间&#xff09; 补间&#xff0c;一般指补间动画&#xff0c;例如uni…

Ceph集群的部署

一、Ceph集群的部署 1、集群环境 1.1 集群架构 主机名业务IP存储IP服务器配置系统类型集群角色ceph-mon1-deploy172.17.10.61/16192.168.10.61/242C/4GUbuntu1804mondeploy(部署节点)ceph-mon2172.17.10.62/16192.168.10.62/242C/4GUbuntu1804mon(监控节点)ceph-mon3172.17.…

fun函数方法体=返回值,kotlin

fun函数方法体返回值&#xff0c;kotlin var str: String "fly"fun main(args: Array<String>) {println(getMyString())println(getMyInt())str "phil"println(getMyString())println(getMyInt()) }fun getMyInt(): Int {return if (str.equals(&…

javaweb学习4

作业 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script type"text/javascript">//动态绑定表单提交window.onloadfunction (){//得到form2的dom对象var fo…

多元分类预测 | Matlab基于北方苍鹰优化深度置信网络(NGO-DBN)的分类预测,多输入模型,NGO-DBN分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab基于北方苍鹰优化深度置信网络(NGO-DBN)的分类预测,多输入模型,NGO-DBN分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可…

在IDEA中如何查看svn版本提交历史记录

1.查看svn版本历史记录方法一 2.查看svn版本历史记录方法二 ①拉取远程库代码 ②提交本地代码到远程 ③查看历史记录 ④回退代码 3.查看历史版本记录的提交 4.选择上图中某次提交记录再次选图中序号4

python接口自动化(十九)--Json 数据处理---实战(详解)

简介 上一篇说了关于json数据处理&#xff0c;是为了断言方便&#xff0c;这篇就带各位小伙伴实战一下。首先捋一下思路&#xff0c;然后根据思路一步一步的去实现和实战&#xff0c;不要一开始就盲目的动手和无头苍蝇一样到处乱撞&#xff0c;撞得头破血流后而放弃了。不仅什么…

模块联邦实践

在聊模块联邦之前&#xff0c;我们先了解下在多个项目下&#xff0c;前端模块如何复用的 跨项目模块复用方案 1、npm 包包管理工具对于前端应用来说不可或缺&#xff0c;我们可以将模块上传到 npm 包&#xff0c;在需要的项目中引入&#xff0c;以此来复用一些公用模块。 2、mo…

基于CANN的AI推理最佳实践丨多路极致性能目标检测应用设计解密

当前人工智能领域&#xff0c;最热门的无疑是以ChatGPT为代表的各种“新贵”大模型&#xff0c;它们高高在上&#xff0c;让你无法触及。但在人们的日常生活中&#xff0c;实际应用需求最大的还是以Yolo模型为代表的目标检测“豪强”&#xff0c;它们每天都在以各种方式落地、应…

javascript匿名函数之立即调用函数

今天在看youtube的前端代码时发现了一个很奇怪的写法&#xff0c;从来没见过&#xff0c;代码如下&#xff1a; (function(e, c, l, f, g, h, k) {var d window;d.getInitialData function() {var b window;b.ytcsi && b.ytcsi.tick("pr", null, "&…

TensorFlow基础和入门案例

TensorFlow简介 TensorFlow是目前主流深度学习框架之一&#xff0c;其库中几乎包含了所有机器学习和深度学习相关的辅助函数和封装类&#xff0c;官方文档如下图所示。在其框架下做各种神经网络算法的开发可以极大减轻工作量&#xff0c;在入门阶段可以不需要深入理解相关优化…

spring拦截器参数及多拦截器执行顺序讲解

1.拦截器中的参数 2.多拦截器执行顺序 如果全部返回true&#xff0c;则按照流程全部执行 如果3返回false&#xff0c;123的preHandler会执行&#xff0c;123的postHandler都不会执行&#xff0c;但是return为true的2和1的after会执行 如果2返回false 12的preHandler会执行 pos…

sql 模糊查询与查询时间范围 起止时间

上代码 <select id"page" resultType"com.sky.entity.Orders">select * from orders<where><if test"number!null and number!">and number like concat(%,#{number},%)</if><if test"phone!null and phone!&q…