算法训练 —— 链表(2)

news2024/11/15 5:10:56

目录

1. LeetCode24. 两两交换链表中的结点

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

3. LeetCode160.相交链表

4. LeetCode141.环形链表

5. LeetCode142.环形链表II

6. LeetCode138.复制带随机指针的链表 


1. LeetCode24. 两两交换链表中的结点

两两交换链表中的结点 

/*解法1:迭代。。设置虚拟头结点*/
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* res = new ListNode(-1);// 设置一个虚拟头结点
        res->next = head;// 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = res;
        while(cur->next != nullptr && cur->next->next != nullptr)
        {
            ListNode* tmp = cur->next;// 记录临时节点
            ListNode* tmp1 = cur->next->next->next;

            cur->next = cur->next->next;  // 步骤一
            cur->next->next = tmp;        // 步骤二
            cur->next->next->next = tmp1; // 步骤三

            cur = cur->next->next;// cur移动两位,准备下一轮交换
        }
        return res->next;
    }
};

 

 

/*解法2:递归*/
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //如果链表结点个数为0或1,这时候直接返回head,不需要交换
        if(head == nullptr || head->next == nullptr) return head;

        ListNode* prev = head;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;

        //交换两个节点
        prev->next = next;
        cur->next = prev;

        //以 1->2->3->4->5->nullptr 为例
        //交换之后为 2->1->3->4->5->nullptr
        //因为head是指向1的,所有递归调用的结果返回给head->next
        head->next = swapPairs(next);
        return cur;
        
    }
};

解法2图解: 

 

//解法3:
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* newhead = head->next;
        ListNode* tmp = nullptr;
        ListNode* prev = head;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;
        while(prev != nullptr && prev->next != nullptr)
        {
            cur->next = prev;
            prev->next = next;
            if(tmp != nullptr) tmp->next = cur;
            tmp = prev;
            prev = next;
            if(prev != nullptr)cur = prev->next;
            if(cur != nullptr) next = cur->next;
        }
        return newhead;
    }
};

        解法3:是不用虚拟的头结点,直接在原链表交换,是一种不错的思路,但是理解起来不是那么容易,建议上面两种方法的理解,下面是图解过程

 

 

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

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

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //给链表设置一个虚拟头结点(哨兵结点),有效防止删除正数第一个的情况,避免更新头结点
        ListNode* res = new ListNode(-1);
        res->next = head;
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* prev = res;
        while(n--)//因为题目中n是有效的,所以我们让快指针先走n步
        {
            fast = fast->next;
        }
        while(fast)//然后fast和slow一起走
        {
            fast = fast->next;
            prev = slow;//一起走之前,先记录一下slow的位置,当fast走到空时,slow一定走到了倒数第n个节点上
            slow = slow->next;
        }
        prev->next = slow->next;
        return res->next;
    }
};

 

3. LeetCode160.相交链表

相交链表 

 

//解法1:
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* pA = headA;
        ListNode* pB = headB;
        //你可以算一算图中的pA走完headA从headB开始走到交点,和pB走完headB从headA开始走到交点距离是一样的
        while(pA != pB)//pA == pB时退出,表明走到了交点
        {
            // pA 将headA链表走完了,就去走headB链表
            pA = pA == nullptr ? headB : pA->next;
            // pB 将headB链表走完了,就去走headA链表
            pB = pB == nullptr ? headA: pB->next;
        }
        return pA;
    }
};

//解法2;
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* tailA = headA;
        ListNode* tailB = headB;
        int lenA = 1;
        while(tailA->next)//计算链表A的长度
        {
            ++lenA;
            tailA = tailA->next;
        }

        int lenB = 1;
        while(tailB->next)//计算链表B的长度
        {
            ++lenB;
            tailB = tailB->next;
        }
   
        if(tailA != tailB)//两个链表都走完了,但是不相等,表明一定没有交点
        {
            return nullptr;
        }
        
        int gap = abs(lenB - lenA);//算出长短链表相差多少
        ListNode* shortlist = headA;
        ListNode* longlist = headB;

        if(lenA > lenB)//这里用来准确确定长、短链表
        {
            shortlist = headB;
            longlist = headA;
        }
        
        while(gap--)//让长链表走差距步
        {
            longlist = longlist->next;
        }

        while(longlist != shortlist)//然后长链表和短链表一起走
        {
            longlist = longlist->next;
            shortlist = shortlist->next;
        }
        return longlist;
    }
};

 

4. LeetCode141.环形链表

环形链表 

思路动图:

 

双指针法:

快指针先走两步,紧接着慢指针走

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                return true;
            }
        }
        return false;
    }
};

5. LeetCode142.环形链表II

环形链表II 

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                ListNode* meet = slow;
                while(meet != head)
                {
                    meet = meet->next;
                    head = head->next;
                }
                return head;
            }
            
        }
        return nullptr;
    }
};

6. LeetCode138.复制带随机指针的链表 

 

 

class Solution {
public:
    Node* copyRandomList(Node* head) {
        //1.拷贝源节点并链接
        Node* cur = head;
        while(cur)
        {
            Node* copy = new Node(cur->val);
            copy->next = cur->next;
            cur->next = copy;
            cur = copy->next;
        }
        cur = head;
        //2.根据原节点,处理copy节点的random
        
        while(cur)
        {
            Node* copy = cur->next;
            if(cur->random == nullptr)
            {
                copy->random = nullptr;
            }
            else
            {
                copy->random = cur->random->next;
            }
            cur = copy->next;
        }
        cur = head;

        //3.把拷贝节点解下来,链接成新链表。同时恢复原链表;
        Node* copyhead, *copytail;
        copyhead = copytail = nullptr;
        while(cur)
        {
            Node* copy = cur->next;
            Node* next = copy->next;
            if(copytail == nullptr)
            {
                copyhead = copytail = copy;
            }
            else
            {
                copytail->next = copy;
                copytail = copy;
            }
            cur->next = next;
            cur = next;
        }
        return copyhead;
    }
};

 

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

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

相关文章

机器学习时间序列特征处理与构造,这篇我建议你收藏

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。 那特征工程是什么? 特征工程是利用数据领域的相关…

vue3 antd项目实战——Form表单使用【v-model双向绑定数据,form表单嵌套input输入框、Radio单选框】

vue3 ant design vue项目实战——单选框(Radio)的使用以及Form表单的双向绑定知识调用(form表单的源代码附在文章最后)场景复现实现需求form表单整体架构的搭建input输入框文本域的嵌套单选组合Radio的嵌套button按钮组合的嵌套fo…

小米手机不为人知的秘密—后台静默安装任何应用

导读你是否拥有一台小米,HTC,三星或者是一加的 Android 手机呢?如果回答是肯定的,那么你应该意识到,几乎所有的智能手机厂商提供的定制 ROM,如 CyanogenMod、Paranoid Android、 MIUI 或者一些其它的 ROM 都…

再谈指针(12)

目录 1、字符指针 2、指针数组 3、数组指针 1、定义 2、&数组名VS数组名 3、数组指针的使用 1、二维数组的数组名 4、数组参数、指针参数 1、一维数组传参 2、二维数组传参 3、一级指针传参 4、二级指针传参 5、函数指针 6、函数指针数组 7、指向函数指针数…

SpringCloud之Sleuth全链路日志跟踪

文章目录1 Sleuth链路跟踪1.1 分布式系统面临的问题1.2 Sleuth是什么1.3 Zipkin是什么1.4 链路监控相关术语1.5 实战练习1.5.1 pom.xml1.5.2 添加yml配置1.5.3 添加控制器1.5.4 测试访问1.6 Zipkin1.6.1 下载与启动1.6.2 搭建链路监控步骤1.6.2.1 搭建8990提供者1.6.2.2 搭建89…

08 `.o`中的汇编信息 hopper disassembler 调试 HelloWorld

前言 上周[2020.05.23]想要 直接使用 fastdebug 版本的 jdk 来进行调试, 可惜失败了 原来是 缺少 可执行文件关联的, object file, 里面记录了 关联的源码的一些信息 看来还是 免不了, 需要 手动 编译 open jdk, 哎 本文主要是两个东西 : 1. 查看 object file 中的汇编信…

CSS权威指南(一)CSS概述

文章目录1.元素2.引入样式表3.样式表4.媒体查询5.特性查询1.元素 (1)置换元素和非置换元素 置换元素,指用来置换元素内容的部分不由文档内容直接表示。比如img标签。非置换元素,元素的内容是由用户代理在元素自身生成的框中显示…

这样的C盘或许还有?救救C盘......

C盘红了!!! 大部分软件默认缓存在C盘(有的甚至只能安装到C盘) C盘太满电脑运行会很卡顿 对于这种情况,为了节约C盘空间,我们可以将这些被迫存在C盘的文件挪到其他盘 但是有的应用无法更改默…

C++ 显示图片

编译环境为codeblocks 20.03&#xff0c;编译器为mingw64非自带的版本&#xff08;版本号多少忘记了&#xff09; 头文件 #include <graphics.h>//图形库 #include <conio.h>//_getch() 显示图片代码 int main() {initgraph(640,360,EX_SHOWCONSOLE);//初始化绘…

我亲身经历的2022年软件质量工作——测试工作的经验总结及一些建议

2022年对于大部分人来说都是辛苦的一年。对于整个社会&#xff0c;疫情反反复复&#xff0c;折磨的每一个人都心力交瘁。 经济下滑&#xff0c;失业率上升似乎听到的都是不好的消息。对于整个互联网行业也频频传出大厂裁员的消息。 而质量团队在大厂的裁员计划里也是首当其冲。…

4)Django模型,表单,视图,路由

目录 一 Django模型 Django ORM 数据库配置 Django 如何使用 mysql 数据库 实例 定义模型 创建 APP 数据库操作 添加数据 获取数据 更新数据 删除数据 二 Django 表单 HTTP 请求 GET 方法 POST 方法 Request 对象 QueryDict对象 三 Django视图 视图层 请求…

Vault的程序侧接入方式-AppRole

前言&#xff1a; 程序侧的接入对于Vault来说也是一种Accessor的接入&#xff0c;而AppRole绝对不是Vault首推的程序侧接入方式&#xff0c;但它是最方便的接入方式。 AppRole的本质是由Vault为程序单独引入一套由Vault托管的鉴权方式&#xff0c;对于安全平台来说没引入一套…

videojs-flvjs:video.js + flv.js播放m3u8和flv视频

videojs-flvjs是video.js的扩展&#xff0c;让video.js支持flv.js播放器&#xff0c;可以在video.js的techOrder里配置flvjs播放器。 下面做了一个切换m3u8和flv直播流的简易工具&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta ch…

线程安全(万字详解)

目录 线程安全 概念 用一段代码感受线程安全 线程安全问题的原因 修改上述代码,使其线程安全 synchronized synchronized使用方法 锁对象的规则 synchronized用法,代码展示 monitor lock sychronized的特性 java标准库中的线程安全类 死锁 死锁的常见原因 多个…

LVGL学习笔记9 - 标签Label

目录 1. 显示字符串 1.1 lv_label_set_text 1.2 lv_label_set_text_fmt 1.3 lv_label_set_text_static 2. 设置长字符串模式 3. 改变颜色 3.1 改变背景颜色和对比度 3.2 设置字符串颜色 3.2.1 设置Style的字符串颜色 3.2.2 设置对象的字符串颜色 3.2.3 局部改色 显示…

钧瓷产业将占禹州GDP50%以上,产生千亿市值钧瓷生态型科技公司

这里的上市指沪深的主板&#xff0c;创业板和科创板&#xff0c;区域的挂牌不算。 这个数据是根据禹州钧瓷产业2022年实际税收&#xff0c;综合钧瓷产业报税幅度&#xff0c;钧瓷数据开放平台&#xff0c;钧瓷产业决策内参&#xff0c;钧瓷产业化&#xff0c; 数字化后的预期增…

【CUDA入门笔记】GPU存储结构模型(1)

GPU存储结构模型 1.CPU可以读写GPU设备中的Global Memory、Constant Memory以及Texture Memory内存储的内容&#xff1b;主机代码可以把数据传输到设备上&#xff0c;也可以从设备中读取数据&#xff1b; 2.GPU中的线程使用Register、Shared Memory、Local Memory、Global Mem…

信息时代,企业如何安全管理数据

随着企业信息化的发展&#xff0c;企业所产生的数据量也越来越多&#xff0c;企业数据的存储安全和传输安全管理工作则成为企业数据管理者的重中之重。但是对数据的保护要依靠一定的基础设施&#xff0c;目前&#xff0c;世界各国对数据保护的基础设施建设还是不够完善&#xf…

VSCode搭建ruby开发调试环境

安装rvm rvm是ruby版本管理工具&#xff0c;可以管理本地的ruby的版本 curl -sSL https://get.rvm.io | bash -s stable安装ruby 使用 rvm list known获取已知的ruby版本&#xff0c;这里安装3.0.0版本的ruby rvm install 3.0.0新建ruby文件 在VSCode中新建ruby文件main.r…

【强训】Day1

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、选择二、编程1. 组队竞赛2. 删除公共字符答案1. 选择2. 编程普通小孩也要热爱生活&#xff01; 一、选择 下列选项中属于面向对象编程主要特征的是&#xff08;&#xff09; A 继承 B 自顶向下 C 模块化 D 逐步…