LeetCode 热题 100 | 链表(中上)

目录

1  141. 环形链表

1.1  哈希表

1.2  快慢指针

2  142. 环形链表 II

2.1  哈希表

2.2  快慢指针

3  21. 合并两个有序链表

4  2. 两数相加


菜鸟做题第三周,语言是 C++

1  141. 环形链表

1.1  哈希表

解题思路:遍历链表,在哈希表中查询当前节点地址是否已经存在。若存在,则证明该链表有环,返回 True;若不存在,则将当前节点地址存入哈希表中。如果能够遍历完毕,则返回 False 。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode * p = head;
        unordered_set<ListNode *> set;

        while (p) {
            if (set.find(p) != set.end()) return true;
            set.insert(p);
            p = p->next;
        }

        return false;
    }
};

1.2  快慢指针

解题思路:

  1. 设置一快一慢指针
  2. 快指针每次移动两格,慢指针每次移动一格
  3. 如果快指针能够遇上慢指针,那么链表中存在环

思路说明图:

一开始我会想,兔子一定会在同一节点追上乌龟吗?会不会存在,虽然兔子从后面追上了乌龟,但是直接把乌龟超过了。那循环终止的条件怎么写啊?答案是,不存在这种情况。

巧妙之处就在,兔子虽然快,但是也只是每次移动两格。兔子和乌龟每次产生的差距都为 1,而 1 又是所有整数的因子。因此,假设兔子要从后面追上乌龟,且现在的距离为 N,那么经过 N 个时刻后兔子一定追上乌龟,即它们会相遇。

但如果兔子每次移动的不是两格,它和乌龟每次产生的差距为 d,那么就要考虑 N 能不能被 d 整除了。所以兔子每次移动两格不是随便设置的,而是有一定科学依据的。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if (head == nullptr) return false;

        ListNode * slow = head;
        ListNode * fast = head->next;

        while (slow != fast) {
            if (fast == nullptr || fast->next == nullptr) return false;
            slow = slow->next;
            fast = fast->next->next;
        }
        return true;
    }
};

2  142. 环形链表 II

2.1  哈希表

和上一题的代码几乎一模一样,只是返回的内容不同。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode *> set;
        ListNode * p = head;

        while (p) {
            if (set.find(p) != set.end()) return p;
            set.insert(p);
            p = p->next;
        }

        return nullptr;
    }
};

2.2  快慢指针

虽然用哈希表直接秒了,但是用快慢指针也是能做的。。。

请参考官方题解

3  21. 合并两个有序链表

解题思路:

  1. 设置 p 和 q 指针分管两条链
  2. 比较 p 和 q 所指向的节点的值
  3. 按照从小到大的顺序重新连接

注意:不是发现 p->val 小于 q->val 就赶紧重新连接,而是要让 p 继续往后找,找到最后一个小于 q->val 的 p->val,然后才重新连接。否则,不仅违背了从小到大的排序规则,还丢失了节点之间原本的连接。对于 q->val 小于 p->val 的情况同理。

思路说明图:这四幅图的顺序是从左到右,从上到下。

对于 p->val == q->val 的情况,哪边连哪边都无所谓。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if (list1 == nullptr && list2 == nullptr) return nullptr;
        if (list1 == nullptr) return list2;
        if (list2 == nullptr) return list1;

        ListNode * p = list1, * q = list2;
        while (p && q) {
            if (p->val <= q->val) {
                while (p->next && p->next->val <= q->val) p = p->next;
                ListNode * temp = p->next;
                p->next = q;
                p = temp;
            } else if (p->val >= q->val) {
                while (q->next && p->val >= q->next->val) q = q->next;
                ListNode * temp = q->next;
                q->next = p;
                q = temp;
            }
        }
        return list1->val <= list2->val ? list1 : list2;
    }
};

说明:这两行代码就是我说的 “要让 p 或 q 继续往后找”

while (p->next && p->next->val <= q->val) p = p->next;
while (q->next && p->val >= q->next->val) q = q->next;

4  2. 两数相加

这道题比我想象的简单,我以为要算最后的总和,结果只需要算每一位的结果

解题思路:

  • 设置进位 carry
  • 每一位结果 = (p->val + q->val + carry) % 10
  • 如果 p->val + q->val + carry > 10,则新的 carry = 1

最重要的其实是 l1 和 l2 可能不一样长,因此需要考虑一条链表已经遍历完毕,而另一条链表还没有遍历完毕的情况。因此进行了如下处理:

int n1 = p ? p->val : 0;
int n2 = q ? q->val : 0;
// ...
if (p) p = p->next;
if (q) q = q->next;

如果 p 或者 q 遍历完了,那么用 0 参加加法运算即可。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode * head = new ListNode(0), * tail = head;

        int carry = 0;
        ListNode * p = l1, * q = l2;
        while (p || q) {
            int n1 = p ? p->val : 0;
            int n2 = q ? q->val : 0;
            int sum = n1 + n2 + carry;
            tail->next = new ListNode(sum % 10);
            tail = tail->next;
            carry = sum / 10;
            if (p) p = p->next;
            if (q) q = q->next;
        }

        if (carry) {
            tail->next = new ListNode(carry);
        }

        return head->next;
    }
};

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

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

相关文章

用Audio2Face导出Unity面部动画

开始之前说句话&#xff0c;新年前最后一篇文章了 一定别轻易保存任何内容&#xff0c;尤其是程序员不要轻易Ctrl S 在A2F去往Unity的路上&#xff0c;还要经历特殊Blender&#xff0c;自己电脑中已下载好的可能不是很好使。 如果想查看UE相关的可以跳转到下边这两篇链接 1. …

追觅科技发布全折叠高速吹风机Pocket

2月2日&#xff0c;追觅科技召开2024新品发布会&#xff0c;一系列年度新品亮相。现场&#xff0c;追觅科技发布了个护重磅新品——追觅Pocket折叠高速吹风机&#xff0c;这也是行业首个全折叠高速吹风机。 创新柔性折叠技术&#xff0c;直卷吹一机全能 追觅Pocket折叠高速吹风…

Dash :一个超漂亮的 python Web库!

你好&#xff0c;Dash 是一个非常方便的 Python 库&#xff0c;它可以非常非常帮助你构建基于 Web 的应用程序&#xff0c;而且最棒的是你无需使用 JavaScript&#xff01; 不仅如此&#xff0c;Dash 还是一个专门用于创建分析 Web 应用程序的用户界面库。 如果你是一个使用 …

沟通管理和相关方管理核心考点梳理

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 PMP - 沟通管理和相关方管理核心考点梳理 沟通管理和相关方&#xff08;干系人&#xff09;管理这两章放在一起进行梳理&#xff0c;这两章很多的考点很容易混淆&#xff0c;经常会纠结于一些题目&#xff0c;究竟…

三层架构思想

&#xff08;一&#xff09;回顾 面向对象设计原则&#xff1a; 各司其职&#xff08;单一职责&#xff09;&#xff1a;每个Java对象的职责尽可能单一&#xff0c;每个Java对象只负责做某一件事&#xff0c;目的是为了简单化。 解耦合&#xff08;开闭原则&#xff09;&…

深度学习入门笔记(一)必备数学基础知识

本节中&#xff0c;我们先来介绍一些深度学习中必备的数学知识&#xff0c;有些是大学课堂讲过的&#xff0c;还有些可能没有&#xff0c;对于第一次见到的知识&#xff0c;可以先不用深究&#xff0c;了解概念即可&#xff0c;再后面应用的时候可以翻过头再看。 1.1 线性代数…

github请求超时解决方法

github请求超时解决办法 我使用windows执行如下git命令,提示超时 git clone xxxxx命令行提示如下&#xff1a; Failed to connect to github.com port 443: Timed out问题排查 可我Chrome可以正常访问github甚至ChatGPT&#xff0c;但是为什么在命令行里面却无法访问&#…

OpenAI 悄悄升级 ChatGPT;王腾:小米手机用户忠诚度安卓第一丨 RTE 开发者日报 Vol.140

开发者朋友们大家好&#xff1a; 这里是「RTE 开发者日报」&#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

Java中的常用API

常用API Object类浅克隆与深克隆 ObjectsObjects中的equals 包装类StringBuilder和StringBufferStringBuilder是可变字符串对象StringBuffer线程安全案例![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/87649c20e6464113a42aee5f16f1ee22.png) StringJoiner Object…

鸿蒙harmony--自定义组件

今天是2月1日&#xff0c;星期四&#xff0c;二月的第一条祝福送给你&#xff0c;愿你目之所及皆是欢喜&#xff0c;心之所想皆能如愿&#xff0c;希望在新的一年里&#xff0c;我们都能越来越好。 目录 一&#xff0c;定义 二&#xff0c;自定义组件的基本用法 三&#xff0c;…

生产问题排查系列——未知404状态接口请求

引言 我们的产品主打金融服务领域&#xff0c;以B端客户为我们的核心合作伙伴&#xff0c;然而&#xff0c;我们的服务最终将惠及C端消费者。在技术实现上&#xff0c;我们采用了公司自主研发的微服务框架&#xff0c;该框架基于SpringBoot&#xff0c;旨在提供高效、可靠的服…

【FPGA VerilogModelsim】 8bitBCD码60计数器

可私信获取整个项目文件 8bit 即有8位二进制 BCD码 ,全称Binary-Coded Decimal,简称BCD码或者二-十进制代码 利用四位二进制(0000-1111)16个中选择10个作为十进制0-9; 常见的BCD码是8421码 本项目使用两组BCD码(每组4bit,共8bit,故称为8bitBCD)(高位0-5,低位0-9…

【Java网络编程04】网络原理进阶(二)

1. 前言 在网络原理进阶&#xff08;一&#xff09;部分我们详细介绍了UDP/TCP两大协议及其相关特性&#xff0c;本章我们会讨论网络层、数据链路层、物理层相关协议。但是需要注意的是&#xff0c;如果有小伙伴们未来是想成为Java后端开发工程师的&#xff0c;那么未来工作中…

随着网络的快速发展,网络安全问题也日益凸显,遇到攻击该如何处理,如何抉择合适的防护方案

DexunCloud 经过研究发现当今世界&#xff0c;随着网络的快速发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击被认为是网络安全领域里最为严重的威胁之一。毫无疑问&#xff0c;DDoS攻击不仅可以导致网络服务中断&am…

LCR 156. 序列化与反序列化二叉树

w 解题思路&#xff1a; 序列化 反序列化 public class Codec {public String serialize(TreeNode root) {if(root null) return "[]";StringBuilder res new StringBuilder("[");Queue<TreeNode> queue new LinkedList<>() {{ add(root)…

RK3326系统中集成思必驰音频适配文件

前言 最近本人在RK3326 8.1系统上做定制化&#xff0c;需要对接思必驰平台音频相关接口&#xff0c;同时在系统中集成音频适配文件&#xff0c;踩了很多坑&#xff0c;写这篇文章记录一下。 一、为什么要集成音频适配文件&#xff1f; 当APP&#xff08;集成…

【C语言】通讯录实现(下)

目录 1.进阶通讯录特点&#xff08;下&#xff09; 2.实现步骤 &#xff08;1&#xff09;保存增加的联系人数据到文件中 &#xff08;2&#xff09;加载保存的联系人数据 3.完整C语言通讯录代码 &#xff08;1&#xff09;contact.h (2)test.c (3)contact.c 4.结语 1.…

【Qt加密播放器】登录窗口功能补充

输入框小设计 目的&#xff1a;实现鼠标点击输入框时的聚焦效果。 首先在LoginForm构造函数中为账号和密码输入框添加事件过滤器。关于事件过滤器的具体介绍可以参考这篇博文&#xff1a;Qt消息机制和事件 ui->nameEdit->installEventFilter(this); ui->pwdEdit->…

文字超长显示省略号...坑(如果盒子本身是弹性盒子flex布局会不支持)

如果盒子是弹性盒子 样式会失效 #item-title{font-size: 28rpx;font-weight: 800;color: #2D3748;width: 100%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}&:nth-child(2){width: calc(100% - 172rpx);margin-left: 40rpx;>view{&:not(:first-…

人工智能基础-Numpy矩阵运算-聚合操作

加、减、乘、除、整除 幂、取余、倒数、绝对值 三角函数 e的x次方、3的x次方、logx、log2为底、log10为底 矩阵运算 加、减、乘&#xff08;对应数相乘&#xff09;、矩阵相乘运算、转至 向量和矩阵的运算 加法 对应相加 改变维度后相加 乘法 矩阵的逆 聚合操作 …