代码随想录拓展day4 143.重排链表;141. 环形链表;面试题 02.07. 链表相交

news2024/11/26 6:20:32

代码随想录拓展day4 143.重排链表;141. 环形链表;面试题 02.07. 链表相交

关于链表的一些应用,基本都用到了快慢指针的思路。对于单链表来说,确定边界,也就是遍历时的终止条件非常重要。

143.重排链表

143. 重排链表 - 力扣(Leetcode)

不用额外空间的方法还是比较难的,而且还涉及到了很多coding细节的问题,这里注意要用count的奇偶来判断下一个插入的节点。

思路

本篇将给出三种C++实现的方法

  • 数组模拟
  • 双向队列模拟
  • 直接分割链表

方法一

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

代码如下:

class Solution {
public:
    void reorderList(ListNode* head) {
        vector<ListNode*> vec;
        ListNode* cur = head;
        if (cur == nullptr) return;
        while(cur != nullptr) {
            vec.push_back(cur);
            cur = cur->next;
        }
        cur = head;
        int i = 1; // 注意,head在最开始已经放进数组了,所以下标i从1开始
        int j = vec.size() - 1;  // i j为之前前后的双指针
        int count = 0; // 计数,偶数去后面,奇数取前面
        while (i <= j) {
            if (count % 2 == 0) {
                cur->next = vec[j];
                j--;
            } else {
                cur->next = vec[i];
                i++;
            }
            cur = cur->next;
            count++;
        }
        cur->next = nullptr; // 注意结尾
    }
};

方法二

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

class Solution {
public:
    void reorderList(ListNode* head) {
        deque<ListNode*> que;
        ListNode* cur = head;
        if (cur == nullptr) return;

        while(cur->next != nullptr) {
            que.push_back(cur->next); // 第一个放进去的是head->next
            cur = cur->next;
        }

        cur = head;
        int count = 0; // 计数,偶数去后面,奇数取前面
        ListNode* node;
        while(que.size()) {
            if (count % 2 == 0) {
                node = que.back();
                que.pop_back();
            } else {
                node = que.front();
                que.pop_front();
            }
            count++;
            cur->next = node;
            cur = cur->next;
        }
        cur->next = nullptr; // 注意结尾
    }
};

方法三

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

如图:

在这里插入图片描述

这种方法,比较难,平均切割链表,看上去很简单,真正代码写的时候有很多细节,同时两个链表最后拼装整一个新的链表也有一些细节需要注意!

代码如下:

class Solution {
private:
    // 反转链表
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }

public:
    void reorderList(ListNode* head) {
        if (head == nullptr) return;
        // 使用快慢指针法,将链表分成长度均等的两个链表head1和head2
        // 如果总链表长度为奇数,则head1相对head2多一个节点
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast && fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* head1 = head;
        ListNode* head2;
        head2 = slow->next;
        slow->next = nullptr;

        // 对head2进行翻转
        head2 = reverseList(head2);

        // 将head1和head2交替生成新的链表head
        ListNode* cur1 = head1;
        ListNode* cur2 = head2;
        ListNode* cur = head;
        cur1 = cur1->next;
        int count = 0; // 偶数取head2的元素,奇数取head1的元素
        while (cur1 && cur2) {
            if (count % 2 == 0) {
                cur->next = cur2;
                cur2 = cur2->next;
            } else {
                cur->next = cur1;
                cur1 = cur1->next;
            }
            count++;
            cur = cur->next;
        }
        if (cur2 != nullptr) { // 处理结尾
            cur->next = cur2;
        }
        if (cur1 != nullptr) {
            cur->next = cur1;
        }
    }
};

141. 环形链表

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

快慢指针的一个应用。同时哈希表也可以解决这个问题,但是需要额外的空间。

思路

可以使用快慢指针法, 分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢?

首先第一点: fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。

那么来看一下,为什么fast指针和slow指针一定会相遇呢?

可以画一个环,然后让 fast指针在任意一个节点开始追赶slow指针。

会发现最终都是这种情况, 如下图:

在这里插入图片描述

fast和slow各自再走一步, fast和slow就相遇了

这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

动画如下:

在这里插入图片描述

C++代码如下

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,说明有环
            if (slow == fast) return true;
        }
        return false;
    }
};

或者使用哈希表的方法,把所有遇到过的节点都加入表中,如果有节点重复出现了,因为是单链表,那一定是链表中有环了。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        unordered_set<ListNode*> set;
        ListNode* cur = head;
        while(cur){
            if(set.find(cur) != set.end()){
                return true;
            } else {
                set.insert(cur);
            }
            cur = cur->next;
        }
        return false;
    }
};

面试题 02.07. 链表相交

面试题 02.07. 链表相交 - 力扣(Leetcode)

旧题目复习,依然是快慢指针的应用,同时用哈希表也可以解决。记住重点是单链表相交结尾必相同。

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

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

相关文章

Web前端105天-day65-ToolChain

ToolChain01 目录 前言 一、Webpack 二、指南 总结 前言 ToolChain01学习开始 一、Webpack 官网&#xff1a;webpack 浏览器仅支持: html css 和 js 三种语言实际开发中: 会使用到其他的一些语言, 例如 TS, sass, scss 等.... 这些语言开发起来更加方便快捷, 但是浏览器不…

pinia 笔记

1、安装 npm i pinia -S2、创建store基本结构 1、在src下创建store文件夹并创建app.js文件&#xff0c;同时编写基本代码结构 // 引入实例化store的函数 import { defineStore } from "pinia";// 实例出一个名为app的store,那appStore是什么&#xff1f;它代表当前…

【SpringMVC】SpringMVC实现文件上传

1.一般的文件上传 1.1 文件上传的必要前提 form 表单的 enctype 取值必须是&#xff1a;multipart/form-data(默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型 method 属性取值必须是 Post 提供一个文件选择域<input type"file" /&…

代码随想录二刷day2

代码随想录复习 文章目录代码随想录复习209.长度最小的子数组&#xff08;滑动窗口&#xff09;76.最小覆盖子串904.水果成篮59.螺旋矩阵2螺旋矩阵1209.长度最小的子数组&#xff08;滑动窗口&#xff09; 209.长度最小的子数组 复习一下滑动窗口&#xff0c;滑窗的复杂度还是…

MySQL时间查询讲解+实战教学(查询本月、上个月、下个月等等的数据)

MySql时间查询 MySql查询当前时间 查询 年-月-日 时:分:秒 select now() 查询 年-月-日 select DATE(CURDATE()) 查询 年-月 select date_format(NOW(),%Y-%m) 查询当前年 select YEAR(CURDATE()) 查询当前月 select MONTH(CURDATE()) 查询当前日 select DAYOFMONTH(NOW()) 查…

【论文简述】Efficient Multi-view Stereo by Iterative Dynamic Cost Volume(CVPR 2022)

一、论文简述 1. 第一作者&#xff1a;Shaoqian Wang、Bo Li 2. 发表年份&#xff1a;2022 3. 发表期刊&#xff1a;CVPR 4. 关键词&#xff1a;MVS、深度学习、动态代价体、GRU、迭代优化 5. 探索动机&#xff1a;由于正则化步骤需要较多的GPU内存和处理时间&#xff0c…

大话JMeter4|不同的并发数可以自动化做压测吗?

1080709 23.5 KB 上节课爱画漫画的小哥哥用漫画形式向大家展示了JMeter的进阶用法&#xff1a;如何搭建InfluxDB&#xff0c;使用更炫酷的Grafana。 看到很多小伙伴觉得看的不过瘾&#xff0c;在强烈的催促下&#xff0c;小哥哥的新文章又出来了。这次小哥哥又给我们带来怎样的…

vue + nodejs + npm

node.js下载 1、如图所示&#xff1a; 2、建立node_cache、node_global文件夹&#xff1a; 然后运行以下2条命令 npm config set prefix “D:\node-v14.15.0-win-x64\node_global” npm config set cache “D:\node-v14.15.0-win-x64\node_cache” 执行npm list -global查看&…

编译原理——求短语、直接短语(简单短语)、素短语、句柄

先介绍一下短语、直接短语&#xff08;简单短语&#xff09;、素短语、句柄怎么求&#xff1a;这个图是核心 然后通过一些例题&#xff0c;实战一下&#xff1b; 根据上面介绍的概念、求法&#xff0c;应用一下即可&#xff1b; 例题1 短语&#xff1a;注意对于每一个子树&a…

数字孪生技术助力高炉数字化建设的可行性

随着数字孪生等新一代信息技术的快速发展&#xff0c;数字化转型已成为企业重塑竞争优势的关键举措。依托数字孪生技术&#xff0c;对炼铁高炉进行物联网、数字化信息系统建设&#xff0c;实现了高炉运行状态的数字化监测与预警&#xff0c;数字孪生系统凭借在数字化、模型化、…

利用WordPress搭建属于自己的网站

怎么用WordPress给自己搭建了一个网站&#xff1f;可能很多人都想拥有属于自己的网站&#xff0c;这篇文章就找你怎么利用WordPress搭建属于自己的网站。如果你也正好有搭建个人网站的想法&#xff0c;那么本文会给你一个参考&#xff0c;我尽量写的比较详细&#xff0c;给自己…

【Ctfer训练计划】——(五)

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

Java on VS Code 11月更新|VS Code Java 开发者超200万!

作者&#xff1a;Nick Zhu - Senior Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;我们很高兴与大家分享一个好消息&#xff0c;现在 Visual Studio Code 上已有超过 200 万 Java 开发者&#xff0c;这离不开长期以来社区以…

JavaSE笔记——异常、断言

文章目录前言一、处 理 错 误1.异常分类2.声明受查异常3.如何抛出异常4.创建异常类二、捕获异常1.捕获异常2.捕获多个异常3.再次抛出异常与异常链4.finally 子句5.带资源的 try 语句三、使用断言1.断言的概念2.启用和禁用断言3.使用断言完成参数检查总结前言 在现实世界中却充…

由浅入深学安全-1

由浅入深学安全 常用术语解析 肉鸡 肉鸡也称傀儡机&#xff0c;是指可以被黑客远程控制的机器。 比如用灰鸽子等诱导客户点击或者电脑被黑客攻破或用户电脑有漏洞被种植了木马&#xff0c;黑客可以随意操纵它并利用它做任何事情。 一句话木马 一句话木马主要用来配合菜刀…

【Java系列】还在为Java运算符而烦恼吗?一篇文章带你解答心中烦恼

返回主篇章         &#x1f447; 【Java】才疏学浅小石Java问道之路 Java基本运算符1. 算数运算符分类运算法则2. 关系运算符分类注意项3. 逻辑运算符分类运算法则4. 短路逻辑运算符分类运算法则5. 赋值运算符拓展6. 三元运算符格式运算法则7. 自增自减运算符分类使用…

12-Golang中的嵌套分支以及switch语句的用法

Golang中的嵌套分支以及switch语句的用法嵌套分支基本介绍基本语法switch基本介绍基本语法流程图使用细节嵌套分支 基本介绍 在一个分支结构中又完整的嵌套了另一个完整的分支结构&#xff0c;里面的分支的结构称为内层分支外面的分支结构称为外层分支 基本语法 if 条件表达…

声明式服务调用OpenFeign

文章目录一. OpenFeign1. Feign 与 OpenFeign二. OpenFeign的使用三. OpenFeign自定义配置1. 修改日志级别2. 超时控制四. OpenFeign性能优化五. OpenFeign最佳实践1. 继承2. 抽取PS: 本文为作者学习笔记&#xff0c;实际技术参加意义不大&#xff0c;本文将持续改进完善。 一…

Doris(二)

目录1、Doris数据的导入和导出1.1 数据导入1.1.1 Broker Load1.1.1.1 适用场景1.1.1.2 基本原理1.1.1.3 基本语法1.1.1.4 导入示例1.1.1.5 查看导入1.1.1.6 取消导入1.1.2 Stream Load1.1.2.1 适用场景1.1.2.2 基本原理1.1.2.3 基本语法1.1.2.4 导入示例1.1.2.5 取消导入1.1.3 …

蓝牙耳机什么牌子好?性价比最高的蓝牙耳机排行榜

近年来&#xff0c;蓝牙耳机品牌与日俱增&#xff0c;可供人们选择的范围也越来越大。当然&#xff0c;主打性价比的蓝牙耳机品牌也有很多&#xff0c;下面&#xff0c;我来给大家分享几款性价比最高的蓝牙耳机&#xff0c;一起来看看吧。 一、南卡小音舱蓝牙耳机 售价&#…