Leetcode编程练习

面试题-消失的数字

. - 力扣(LeetCode)

class Solution 
{
public:
    void reverse(vector<int>& nums, int start, int end) 
    {
        while (start < end) 
        {
            swap(nums[start], nums[end]);
            start += 1;
            end -= 1;
        }
    }

    void rotate(vector<int>& nums, int k) 
    {
        // 防止被套圈
        k %= nums.size();

        // 先整体逆置
        reverse(nums, 0, nums.size() - 1);

        // 1. 将逆置到前面的逆置正常顺序
        reverse(nums, 0, k - 1);
        
        // 2. 将后面的也转换正常
        reverse(nums, k, nums.size() - 1);
    }
};
  1. 初始化:
    • int N = nums.size();:获取输入数组 nums 的大小,这表示从0到N-1的连续整数中应该有多少个数字。
    • int x = 0;:初始化一个变量 x,用于存储异或运算的结果。
  2. 第一个for循环:
    • 遍历数组 nums 中的每一个元素,并与 x 进行异或运算。
    • 因为异或运算的性质是:任何数与0异或都等于它本身;任何数与自身异或都等于0。所以,当遍历完数组后,x 中存储的是从0到N-1的所有整数与数组 nums 中实际存在的整数的异或结果。
  3. 第二个for循环:
    • 这个循环从0开始,到N(包括N)结束,与 x 进行异或运算。
    • 理想情况下,如果数组 nums 是完整的,即包含从0到N-1的所有整数,那么在这个循环结束后,x 的值应该是0(因为所有数字都异或了自己,结果为0)。
    • 但是,由于数组 nums 中缺失了一个数字,所以在这个循环结束后,x 的值将是缺失的那个数字(因为缺失的那个数字只被异或了一次,而其他数字都被异或了两次,结果为0)。
  4. 返回结果:
    • 最后,函数返回 x,即缺失的那个数字。

注意:第二个for循环中的 j 是从0遍历到 N(包括N),但实际上,当 j 等于 N 时,它并不与任何数组中的元素异或(因为数组索引是从0到N-1),但这并不影响结果,因为 N 与任何其他数字异或都会得到非零值(除非该数字也是 N,但这种情况不可能发生,因为数组中不可能有 N 这个元素)。

轮转数组

. - 力扣(LeetCode)

class Solution 
{
public:
    void reverse(vector<int>& nums, int start, int end) 
    {
        while (start < end) 
        {
            swap(nums[start], nums[end]);
            start += 1;
            end -= 1;
        }
    }

    void rotate(vector<int>& nums, int k) 
    {
        // 防止被套圈
        k %= nums.size();

        // 先整体逆置
        reverse(nums, 0, nums.size() - 1);

        // 1. 将逆置到前面的逆置正常顺序
        reverse(nums, 0, k - 1);
        
        // 2. 将后面的也转换正常
        reverse(nums, k, nums.size() - 1);
    }
};
  1. reverse 函数是一个辅助函数,用于反转数组 nums 中从索引 start 到 end(不包括 end)的部分。这个函数使用了双指针法,从两端开始交换元素,直到两个指针相遇或交叉。
  2. rotate 函数是主要的旋转函数。首先,它对 k 取模数组的长度 nums.size(),以确保 k 不会超出数组的范围。这是因为如果 k 大于数组的长度,那么实际上只需要旋转 k % nums.size() 次即可。
  3. 接下来,rotate 函数执行三次反转操作:
    • 第一次反转:对整个数组 nums 进行反转。这样,原本在末尾的 k 个元素现在就被移动到了数组的开头,但顺序是反的。
    • 第二次反转:对数组的前 k 个元素(索引从 0 到 k-1)进行反转。这样,原本在数组开头的 k 个元素(但顺序是反的)现在就被转回了正常顺序。
    • 第三次反转:对数组从索引 k 到末尾的部分进行反转。这样,剩余的元素也被转回了正常顺序。

经过这三次反转操作后,数组就被成功地旋转了 k 个位置。

这种方法的关键在于理解如何通过反转操作来重新排列数组中的元素。它避免了使用额外的空间,并且时间复杂度为 O(n),其中 n 是数组的长度。

回文链表

链表的回文结构_牛客题霸_牛客网

class PalindromeList
{
public:
    bool chkPalindrome(ListNode* A)
    {
        // 如果链表为空或者只有一个节点,那么它一定是回文的
        if (A == nullptr || A->next == nullptr)
            return true;

        // 快慢指针找出中间节点,slow 指针指向链表中间位置(如果链表长度是奇数,则指向中间节点;如果是偶数,则指向中间两个节点的第一个)
        ListNode* slow = A;
        ListNode* fast = A;
        while (fast != nullptr && fast->next != nullptr)
        {
            fast = fast->next->next;
            slow = slow->next;
        }

        // 反转后半部分链表,prev 指针指向反转后的链表头部
        ListNode* prev = nullptr;
        ListNode* curr = slow;

        while (curr != nullptr)
        {
            ListNode* temp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = temp;
        }

        // 检查回文,p1 指针指向链表头部,p2 指针指向反转后的链表头部
        ListNode* p1 = A;
        ListNode* p2 = prev;
        while (p1 != nullptr && p2 != nullptr)
        {
            // 如果节点值不相等,则链表不是回文的
            if (p1->val != p2->val)
            {
                return false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }

        // 链表是回文的
        return true;
    }
};

找中间节点

// 快慢指针找出中间节点,slow 指针指向链表中间位置(如果链表长度是奇数,则指向中间节点;如果是偶数,则指向中间两个节点的第一个)
    ListNode* slow = A;
    ListNode* fast = A;
    while (fast != nullptr && fast->next != nullptr)
    {
        fast = fast->next->next;
        slow = slow->next;
    }

定义了两个指针 slow 和 fast,初始时它们都指向链表的头部。在循环中,fast 指针每次向前移动两步,而 slow 指针每次向前移动一步。当 fast 指针到达链表的末尾时,slow 指针就会指向链表的中间位置。

  • 该步骤用来分割链表,以便后续操作

反转后半链表

// 反转后半部分链表,prev 指针指向反转后的链表头部
        ListNode* prev = nullptr;
        ListNode* curr = slow;

        while (curr != nullptr)
        {
            ListNode* temp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = temp;
        }

就是将后半部分的链表每个节点next指向前一个节点,这样就形成了反转链表,链表头是翻转前的最后一个节点。
值得注意:前半部分的最后一个节点的next还是指向翻转前的后半部分第一个节点(也就是后半部分反转后的最后一个节点),所以在后续进行判断两个链表是否相同的时候直接向后进行判断就可以。

检查两个链表

        // 检查回文,p1 指针指向链表头部,p2 指针指向反转后的链表头部
        ListNode* p1 = A;
        ListNode* p2 = prev;
        while (p1 != nullptr && p2 != nullptr)
        {
            // 如果节点值不相等,则链表不是回文的
            if (p1->val != p2->val)
            {
                return false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }

        // 链表是回文的
        return true;
    }

使用一个循环来比较两个指针所指向的节点值。如果发现任何一个节点值不相等,就意味着链表不是回文的,我们直接返回 false。如果循环完成后都没有发现不相等的节点值,那么链表就是回文的,我们返回 true。

相交链表

class Solution 
{
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) 
    {
        if (headA == nullptr || headB == nullptr) 
        {
            return nullptr;
        }
        ListNode* pA = headA, * pB = headB;

        // 如果有交点,那么在第一次相同的时候就会返回pa
        while (pA != pB) 
        {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        // 换道思想,如果两个链表长度不同,可以理解为补长度,
        // 然后重新回到另一个链表的头的那个长度和和另一个指针指向剩余的长度相同,然后就可以达到一个相同的交点
        return pA;
    }
};

对于以下代码可能理解的时候存在一些误区,所以我作出以下思路整理:

        while (pA != pB) 
        {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        // 换道思想,如果两个链表长度不同,可以理解为补长度,
        // 然后重新回到另一个链表的头的那个长度和和另一个指针指向剩余的长度相同,然后就可以达到一个相同的交点
        return pA;

image.png

  1. 假设链表 A 和链表 B 的长度不同,我们让指针从另一个链表的头部重新开始遍历,实际上就是将短链表的指针向前移动了长度差的距离,以此来“补齐长度”。
  2. 当两个指针再次开始从头部出发时,它们之间的距离就会相等,这时它们就像在同一起跑线上开始了新的竞赛。
  3. 当两个指针在两个链表中遍历时,它们会同时移动相同的步数。这样,当它们到达交点时,它们就会处于相同的位置,即使两个链表的长度不同。

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

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

相关文章

python爬虫(一)之 抓取极氪网站汽车文章

极氪汽车文章爬虫 闲来没事&#xff0c;将极氪网站的汽车文章吃干抹尽&#xff0c;全部抓取到本地&#xff0c;还是有点小小的难度。不能抓取太快&#xff0c;太快容易被封禁IP&#xff0c;不过就算被封了问题也不大&#xff0c;大不了重启路由器&#xff0c;然后你的IP里面又…

谷歌明年6月关闭 Google Fit 运动记录API,要求开发者迁移至Android Health平台 | 最新快讯

5 月 6 日消息&#xff0c;谷歌近日发布官方新闻稿&#xff0c;宣布将在明年 6 月使用 Android Health 平台取代 Google Fit 运动记录 API&#xff0c;开发人员应当尽早启动迁移计划。 谷歌自 2022 年起逐渐扩大对 Android Health 平台的投资&#xff0c;旨在减少平台碎片化&am…

在uni-app开发的小程序中引入阿里的多色图标

uniapp不支持阿里多色图标&#xff0c;需要使用工具iconfont-tools进行处理 1.首先 在阿里图标库将 需要的图标添加到项目中 并下载压缩包&#xff0c;取出iconfont.js文件 2.安装iconfont-tools,安装完成会显示出安装到了电脑的那个目录 3&#xff0c;进入目录就会看到下面的…

Maria DB 安装(含客户端),看这一篇就够了

文章目录 一 安装前准备1 版本与Win平台对应2 推荐安装 二 安装步骤1 安装主体程序2 添加系统路径Path 三 客户端 一 安装前准备 1 版本与Win平台对应 版本对应关系可参考&#xff1a; https://www.codebye.com/mariadb-deprecated-package-platforms.html。 2 推荐安装 经…

STM32F4xx开发学习—GPIO

GPIO 学习使用STM32F407VET6GPIO外设 寄存器和标准外设库 1. 寄存器 存储器映射 存储器本身是不具有地址的&#xff0c;是一块具有特定功能的内存单元&#xff0c;它的地址是由芯片厂商或用户分配&#xff0c;给存储器分配地址的过程就叫做存储区映射。给内存单元分配地址之后…

spring高级篇(十)

1、内嵌tomcat boot框架是默认内嵌tomcat的&#xff0c;不需要手动安装和配置外部的 Servlet 容器。 简单的介绍一下tomcat服务器的构成&#xff1a; Catalina&#xff1a; Catalina 是 Tomcat 的核心组件&#xff0c;负责处理 HTTP 请求、响应以及管理 Servlet 生命周期。它包…

excel中数据筛选技巧

1、筛选excel中破折号前后都为空的数据 在Excel中查找破折号前后为空的数据&#xff0c;你可以结合使用Excel的查找和筛选功能&#xff0c;或者利用一些公式来判断。以下是两种常用的方法&#xff1a; 方法一&#xff1a;使用筛选功能选中数据范围&#xff1a;首先&#xff0c…

题目:排序疑惑

问题描述&#xff1a; 解题思路&#xff1a; 做的时候没想到&#xff0c;其实这是以贪心题。我们可以每次排最大的区间&#xff08;小于n&#xff0c;即n-1大的区间&#xff09;&#xff0c;再判断是否有序 。因此只需要分别判断排&#xff08;1~n-1&#xff09;和&#xff08;…

GateWay检查接口耗时

添加gateway依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency>创建一个LogTimeGateWayFilterFactory类&#xff0c;可以不是这个名字但是后面必须是x…

遭遇.halo勒索病毒怎么办?如何识别和应对.halo勒索病毒

导言&#xff1a; 近年来&#xff0c;网络安全问题愈发严峻&#xff0c;其中勒索病毒成为了威胁企业和个人数据安全的重要隐患。在2023年初&#xff0c;一种新的勒索病毒——.halo勒索病毒开始在网络上肆虐&#xff0c;给广大用户带来了极大的困扰。本文91数据恢复将对.halo勒…

NEO 学习之session7

文章目录 选项 A&#xff1a;它涉及学习标记数据。 选项 B&#xff1a;它需要预定义的输出标签进行训练。 选项 C&#xff1a;它涉及在未标记的数据中寻找模式和关系。 选项 D&#xff1a;它专注于根据输入-输出对进行预测。 答案&#xff1a;选项 C 描述了无监督学习的本质&am…

【Pytorch】2.TensorBoard的运用

什么是TensorBoard 是一个可视化和理解深度爵溪模型的工具。它可以通过显示模型结构、训练过程中的指标和图形化展示训练的效果来帮助用户更好地理解和调试他们的模型 TensorBoard的使用 安装tensorboard环境 在终端使用 conda install tensorboard通过anaconda安装 导入类Sum…

判断dll/lib是32/64位、查看lib是导入库/静态库的方法 、查看dll包含的符合、lib包含的函数

一、判断dll/lib是32/64位 原文链接&#xff1a;https://www.cnblogs.com/bandaoyu/p/16752602.html 1. 简便方法&#xff1a; 直接用记事本或者notepad(或txt文本)打开exe文件&#xff08;dll文件&#xff09;&#xff0c;会有很多乱码&#xff0c;不要头疼&#xff0c;接下…

【统计推断】-01 抽样原理之(三)

文章目录 一、说明二、抽样分布三 均值抽样分布3.1 有限母体无放回抽样3.2 有限母体有放回抽样3.3 无限母体 四、比例抽样分布五、和差抽样分布 一、说明 上文中叙述母体和抽样的设计&#xff1b;以及抽样分布的概念&#xff0c;本篇将这种关系定量化&#xff0c;专门针对抽样的…

jmeter后置处理器提取到的参数因为换行符导致json解析错误

现象&#xff1a; {"message":"JSON parse error: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Ill…

ModuleNotFoundError: No module named ‘pkg_resources‘ 问题如何解决?

ModuleNotFoundError: No module named pkg_resources 通常是因为 Python 环境中缺少 setuptools 模块。pkg_resources 是 setuptools 包的一部分&#xff0c;用于处理 Python 包的发行和资源。 为解决这个问题&#xff0c;请按照以下步骤操作&#xff1a; 确保 setuptools 已…

Pytorch基础:内置类type的用法

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 在python中&#xff0c;一切数据类型都是对象&#xff08;即类的实例&#xff09;&#xff0c;包括整数、浮点数、字符串、列表、元组、集合、字典、复数、布尔、函数、…

websevere服务器从零搭建到上线(四)|muduo网络库的基本原理和使用

文章目录 muduo源码编译安装muduo框架讲解muduo库编写服务器代码示例代码解析用户连接的创建和断开回调函数用户读写事件回调 使用vscode编译程序配置c_cpp_properties.json配置tasks.json配置launch.json编译 总结 muduo源码编译安装 muduo依赖Boost库&#xff0c;所以我们应…

npy文件如何追加数据?

.npy 文件是 NumPy 库用于存储数组数据的二进制格式&#xff0c;它包含一个描述数组结构的头部信息和实际的数据部分。直接追加数据到现有的 .npy 文件并不像文本文件那样直接&#xff0c;因为需要手动修改文件头部以反映新增数据后的数组尺寸&#xff0c;并且要确保数据正确地…

【哈希表】Leetcode 14. 最长公共前缀

题目讲解 14. 最长公共前缀 算法讲解 我们使用当前第一个字符串中的与后面的字符串作比较&#xff0c;如果第一个字符串中的字符没有出现在后面的字符串中&#xff0c;我们就直接返回&#xff1b;反之当容器中的所有字符串都遍历完成&#xff0c;说明所有的字符串都在该位置…
最新文章