【Leetcode】vector刷题

Alt

🔥个人主页Quitecoder

🔥专栏Leetcode刷题

Alt

目录

  • 1.只出现一次的数字
  • 2.杨辉三角
  • 3.删除有序数组中的重复项
  • 4.只出现一次的数字II
  • 5.只出现一次的数字III
  • 6.电话号码的字母组合

1.只出现一次的数字

题目链接:136.只出现一次的数字
题目描述在这里插入图片描述

这道题很简单,我们只需要遍历一遍数组,利用异或操作的性质(一个数与自身异或结果为0,任何数与0异或还是其本身)

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int value =0;
        for(auto v:nums)
        {
            value^=v;
        }
        return value;
    }
};

2.杨辉三角

题目链接:118.杨辉三角
题目描述在这里插入图片描述

这道题我们需要构造二维数组,典型的vector的嵌套使用

在这里插入图片描述
首先,我们先构建二维数组,开辟行数大小:

vector<vector<int>> v(numRows);

接着对每一行进行开辟空间,并将两端初始化为1

for(int i=0;i<numRows;i++)
{
    v[i].resize(i+1);
    v[i][0]=1;v[i][i]=1;
}

注意,resize是会进行初始化的,我们没有传值,默认为零

所以我们只需要遍历一遍,遍历到的位置为0,进行相加操作

完整代码如下:

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> v(numRows);
        for(int i=0;i<numRows;i++)
        {
            v[i].resize(i+1);
            v[i][0]=1;v[i][i]=1;
        }
        for(int i=0;i<numRows;i++)
        {
        for(int j=0;j<i;j++)
        {
            if(v[i][j]==0)
            {
                v[i][j]=v[i-1][j]+v[i-1][j-1];
            }
        }
        }
    return v;
    }
};

3.删除有序数组中的重复项

题目链接:26.删除有序数组中的重复项
题目描述在这里插入图片描述

这题是一道简单的双指针思路的题,由于已经排序好,我们只需要设置两个索引,一个向后遍历,若与前面的索引指向值不相同,则对前面的值进行修改

lass Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if (nums.size() == 0) {
            return 0;
        }
        int slow = 0;
        for (int fast = 1; fast < nums.size(); fast++) {
            if (nums[fast] != nums[slow]) {
                slow++;
                nums[slow] = nums[fast];
            }
        }
        return slow + 1;
    }
};

完成了值的覆盖过程

4.只出现一次的数字II

题目链接:137.只出现一次的数字II
题目描述在这里插入图片描述

这个问题的解决方案基于位操作和有限状态自动机的原理。我们要处理的数字是32位整数,因此,我们需要考虑每一位相加后的结果。由于除了一个数字以外,其它数字都出现了三次,我们可以构造一个数字的每一位相加后,模3的结果就是这个只出现一次的数字的相应位

思路如下:

使用两个整数变量onestwosones将会记录每个位只出现一次的情况,而twos将会记录每个位出现两次的情况

对于每个数字num及其每一位,我们更新onestwos

  1. 在第i个位置上,如果ones里的位是1,则表示num要么是第一次遇到i位为1,要么是第四次。如果是第四次,我们已经在twos里记录了两次,所以这次应该把ones里的该位清零,否则保持不变

  2. 同理,如果twos里的位是1,则是第二次遇到i位为1或者是第五次。如果是第五次,我们既要在ones里面加1,同时也要在twos里面清零该位,否则保持不变

  3. 由于我们只需要考虑每个位上1出现的次数,所以任何时候位上的1出现3次,我们都应该清零

最后,ones保留的就是每位上出现一次的结果,而twos将会是0。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ones = 0, twos = 0;       
        for (int num : nums) {
            ones = (ones ^ num) & ~twos;
            twos = (twos ^ num) & ~ones;
        }
        return ones;
    }
};

当我们讨论处理出现三次的数字和一个只出现一次的数字时,onestwos 的位操作确实是难以理解的 ,分解这两行代码:

对于每一个新的数字 num,我们用 onestwos 来跟踪彼此独立的状态:

  1. ones = (ones ^ num) & ~twos;

这里,我们正更新 ones 以包含出现一次的位。让我们分解这行代码:

  • ones ^ num:这个按位异或操作背后的思想是:当前的 ones 表示上一步迭代中已经出现一次的位。当我们再次看到这些位时(即 num 中的对应位也是1),我们希望重置 ones 中的那些位(因为出现一次变成了两次)。对于 num 中新出现的1,ones 中还没有记录,这将被加进 ones

  • & ~twos:接下来的按位与操作~twos 结合表示:我们删除 twos 中已经出现两次的位。~twos 是对 twos 取反,意味着取出 twos 中为0的位。只有那些在 twos 中没有记录(即还没达到两次)的1才应该加入 ones。即使刚才 ones ^ num 把某些位变成了1,若那些位在 twos 中已经出现过两次,我们必须确保它们在 ones 中不变成1

结合二者,ones 在每次迭代结束时仅保留那些恰好出现一次的位。如果某位在 ones 中变成了1但已经在 twos 中出现过,我们需要重置 ones 中的那位为0

  1. twos = (twos ^ num) & ~ones;

接着我们更新 twos 来反映那些已经看到两次的位:

  • twos ^ num:与更新 ones 类似,我们对于每个新来的 num,我们都会用按位异或更新 twos。如果在 twos 中的位是1,且对应的 num 中的位也是1,那么它们会重置为0,因为现在这个位出现了第三次,而我们的目标是找到出现了一次和两次的位。如果出现的是一个新的1(即 num 中的1,而 twos 中并没有记录),twos 就会记录它。这会出现加到三的情况,我们随后会处理。

  • & ~ones:这个按位与操作保证如果在 ones 中有1(意味着这个位已经出现了一次),我们不会在 twos 中加入该位。如果某个位同时在 onestwos 中出现,这意味着这个位出现了3次,并且最终会被忽略。

通过 & ~ones,我们确保了一个位仅仅当它在 num 中为1且在 ones 中尚未出现(即 ones 中为0)时,才会被加入 twos

总结来说,这两步操作是相互独立并且排他的:它们保证一个位在 onestwos 中出现,但不会同时出现。我们在整体数组中使用循环来考虑每个数字的影响。最终,由于所有出现三次的数字在这两个变量中都被消去,ones 会留下那个出现一次的唯一位

5.只出现一次的数字III

题目链接:260.只出现一次的数字III
题目描述在这里插入图片描述

此类问题可以通过位运算(异或操作)来解决。首先,我们可以通过对所有数组元素执行异或操作来找出两个只出现一次的元素的异或结果。因为异或操作具有交换律和结合律,同时一个数字和自己进行异或会变成0,所以最终剩下的结果就是那两个只出现一次的数字的异或结果

这个结果中至少有一个位是1(否则这两个数相同),我们可以找到这个数中的任何一个为1的位,用它来把原数组分成两组,一组在该位上是1,一组在该位上是0。这样每组就包含了一个只出现一次的数字和一些成对出现的数字。然后再对这两个组分别进行异或操作,即可得到这两个只出现一次的数字。

下面是这个算法实现:

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        // 第一步,对所有元素进行异或,最终的结果就是两个只出现一次数的异或结果
        int diff = 0;
        for (int num : nums) {
            diff ^= num;
        }
        
        // 找到diff中任何为1的位,可以使用diff & -diff快速找到
        // 这个操作可以隔离出diff最右端的1
        unsigned int diff_unsigned = diff;
        diff_unsigned &= -diff_unsigned;

        // 使用找到的这一位将数组中的数字分成两组
        vector<int> results(2, 0); // 最终结果
        for (int num : nums) {
            if ((num & diff_unsigned) == 0) {
                // 第一组,与diff_unsigned对应位为0
                results[0] ^= num;
            } else {
                // 第二组,与diff_unsigned对应位为1
                results[1] ^= num;
            }
        }
        
        return results;
    }
};

在这个代码中:

  • diff_unsigned 最终会被设置为两个目标数字的异或结果。
  • diff_unsigned &= -diff_unsigned; 的结果是取出 diff_unsigned 最右边的1位,也就是两个只出现一次的数在这一位上不同的地方。
  • 然后我们通过判断这一位是否为1来将全部数字分为两组,并再次分别对它们进行异或操作,以此找到两个只出现一次的数。

这条语句 diff_unsigned &= -diff_unsigned; 是一种计算机用来找到一个数字中最右边的1的位,并且保持所有其他位为0的技巧。为了更好地理解这个技巧,我们需要先了解计算机中的数字表示——特别是补码表示法,因为这个技巧与负数的二进制表示相关

在补码表示中,一个负数是通过取其正值的二进制表示的反码(每个位取反)然后加1得到的。例如,假设我们有一个4位的系统:

正数 2 的二进制表示:  0010
反码 (invert):      1101
加1得到负数 -2:      1110

观察发现,从正数2的二进制表示到负数-2的表示,最右边的1以及之前的所有0都保持不变,而最右边的1之后的所有位都翻转了。这给了我们一种找到最右边的1的方法。现在,如果我们对2和-2执行按位与操作:

正数 2:                0010
负数 -2:               1110
按位与:                0010

按位与操作的结果就是只有最右边的1保留了下来,其它所有位都变成了0。换句话说,diff_unsigned &= -diff_unsigned; 将结果的所有位都置为0,除了最右边的1所在的位。

在解决问题时,我们首先会通过对所有数字进行异或得到 diff,这代表了两个只出现一次的数字的差异。
diff 变量首先被转换成一个无符号整数 diff_unsigned,然后对它进行取负和按位与操作,以避免未定义行为。这样就保证了即使 diff 的最高有效位是1,我们也不会超出无符号整型的范围

然后使用 diff_unsigned &= -diff_unsigned; 来保留最右边的1,这是两个独特数字在二进制表示中第一个不同的位。

通过这个位的差异,我们可以将所有的数字分成两组来进一步操作,每组包含一个只出现一次的数字以及成对出现的数字。这个1所在的位将用于分辨哪些数字在该位为0或1 —— 这正是对数组进行划分的依据

6.电话号码的字母组合

题目链接:17.电话号码的字母组合
题目描述在这里插入图片描述

这个问题可以通过回溯法解决,这是一种通过穷举所有可能的解来找到全部解的算法。基本思想是从左到右遍历数字字符串,对于每个数字,向当前的字母组合中添加对应的每个字母,然后对剩余的字符串重复这个过程。

下面是递归解决实现:

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        if (digits.empty()) return {}; // 如果输入为空,直接返回空数组
        
        vector<string> mappings = {  // 数字到字母的映射
            "", "", "abc", "def",   // '0','1','2',...
            "ghi", "jkl", "mno",
            "pqrs", "tuv", "wxyz"
        };
        vector<string> result;
        string current;
        
        backtrack(result, digits, 0, current, mappings);
        
        return result;
    }
    
private:
    void backtrack(vector<string>& result, const string& digits, 
                   int index, string& current, const vector<string>& mappings) {
        if (index == digits.length()) { // 如果到达了数字字符串的末尾,就添加当前的字母组合到结果中
            result.push_back(current);
            return;
        }
        
        string letters = mappings[digits[index] - '0']; // 获取当前数字对应的所有字母
        for (char letter : letters) { // 遍历这些字母
            current.push_back(letter);   // 添加当前的字母
            backtrack(result, digits, index + 1, current, mappings);  // 继续处理下一个数字
            current.pop_back();  // 回溯,移除当前字母,以便尝试下一个字母
        }
    }
};

这段代码定义了一个辅助函数 backtrack,用来递归寻找所有可能的字母组合。我们维护一个 current 字符串,它保存当前的部分组合。函数的工作流程是这样的:

  1. 确定终止条件:如果 current 的长度与输入数字字符串的长度相同,说明当前递归路径已经走到头,我们找到了一个完整的字母组合,将其添加到结果中。

  2. 确定递归逻辑:从 mappings 数组中获取当前处理的数字对应的所有可能字母,然后逐一向 current 添加每个字母,并递归地调用自己处理下一个数字。

  3. 回溯处理:每次递归调用完成后,需要将之前添加的字母移除,以便对当前位置尝试不同的字母。

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

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

相关文章

vivado 创建和运行链路清扫

创建和运行链路清扫 要分析给定链路的裕度 &#xff0c; 利用不同 MGT 设置来多次运行链路扫描是很有效的。这样有助于判定最佳设置。 Vivado Serial I/O Analyzer 功能支持您定义、运行、保存和重新调用链路清扫 &#xff0c; 链路清扫是由多次链路扫描集合而成的。 每条…

C++之STL-list+模拟实现

目录 一、list的介绍和基本使用的方法 1.1 list的介绍 1.2 list的基本使用方法 1.2.1 构造方法 1.2.2 迭代器 1.2.3 容量相关的接口 1.2.4 增删查改的相关接口 1.3 关于list迭代器失效的问题 二、模拟实现list 2.1 节点类 2.2 迭代器类 2.3 主类list类 2.3.1 成员变…

软件设计师-重点的创建型设计模式

一、简单工厂&#xff1a; 简单工厂模式属于创建型模式&#xff0c;但不属于23种设计模式之一。 软考中图 二、工厂方法&#xff1a; 意图&#xff1a; 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。 结…

光度立体法估计法线与反射率重建场景

1 从明暗恢复形状 从明暗恢复形状&#xff08;Shape from Shading&#xff0c;SfS&#xff09;是指从图像的明暗信息推断出物体表面几何形状的过程。这个问题假设光照条件已知&#xff0c;目标表面是光滑且均匀的&#xff0c;并且照明是单向的。其基本思想是根据目标表面对光照…

计算机组成原理实验(一)--可控加减法电路设计实验

一、一位全加器的设计 视频学习链接&#xff1a;3-2-4 定点数的加法和减法运算 — 一位全加器的硬件逻辑实现_哔哩哔哩_bilibili 仿真电路图&#xff1a; 总结&#xff1a;奇数个1时Si输出为1&#xff0c;偶数个1输出为0&#xff1b;1的个数大于等于2时&#xff0c;Ci输出1 实…

Kafka 3.x.x 入门到精通(05)——对标尚硅谷Kafka教程

Kafka 3.x.x 入门到精通&#xff08;05&#xff09;——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.2 集群启动2.3 创建主题2.4 生产消息2.5 存储消息2.6 消费消息2.6.1 消费消息的基本步骤2.6.2 消费消息的基本代码2.6.3 消费消息的基本原理2.6.3.1消费者组2.6.3.1.1 消费…

【优秀AI项目】每日跟踪 OpenVoice ,AI快站,OpenVoice

持续更新好玩的开源AI项目或AI商业应用体验 一起来玩转AI&#xff01;&#xff01; 1 huggingface 国内镜像站&#xff1a;AI 快站 HUggingface被墙了&#xff0c;emmmmm 所以我之前玩模型的一大感觉就是 下载什么模型之类的太难受了&#xff01;服了 看到一个镜像站——…

如何使用bof-launcher在CC++Zig应用程序中执行Beacon对象文件(BOF)

关于bof-launcher bof-launcher是一款针对Beacon对象文件&#xff08;BOF&#xff09;的安全测试工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以轻松在C/C/Zig应用程序中执行Beacon对象文件&#xff08;BOF&#xff09;。 Cobalt Strike 4.1于2020年6月25日发…

[Diffusion Model 笔记]DDIM 笔记 数学推导 Denoising Diffusion Implicit Models

目录 核心总结符号定义第一套&#xff0c;快速简单讲清采样方法继续分析&#xff0c;待定系数法求解图示理解关于参数sigma 本文是观看以下视频的笔记&#xff0c;强烈推荐观看最后的图示理解&#xff1a; https://www.bilibili.com/video/BV13P411J7dm/?spm_id_from333.788 论…

数据结构|树形结构|并查集

数据结构|并查集 并查集 心有猛虎&#xff0c;细嗅蔷薇。你好朋友&#xff0c;这里是锅巴的C\C学习笔记&#xff0c;常言道&#xff0c;不积跬步无以至千里&#xff0c;希望有朝一日我们积累的滴水可以击穿顽石。 有趣的并查集剧情演绎&#xff1a;【算法与数据结构】—— 并…

idea自定义配置文件的注释

打开 IntelliJ Idea 软件 依次找到 File—>Editor—>File and Code Templates 设置 Files 下的Class、Interface、Enum等 输入下面的内容 /** * description: ${NAME} * date: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE} * author: author **/

php动态高亮web源代码

php动态高亮web源代码 注&#xff1a;配置好不允许高亮的文件名&#xff0c;安全第一 #php实现动态展示目录树结构源代码 适用于开放源代码&#xff0c;结合html缓存使用效果更佳&#xff0c;因循环较多不适合放首页 能力有限没实现行号 演示&#xff1a;show source|开放…

吉布提国家概况

吉布提国家概况 &#xff08;最近更新时间&#xff1a;2022年10月&#xff09; 【国 名】 吉布提共和国&#xff08;The Republic of Djibouti&#xff0c; La Rpublique de Djibouti&#xff09;。 【面 积】 2.32万平方公里。 【人 口】约100万。主要有伊萨族和阿法尔族。…

认识HTTP

HTTP缺点 通信使用明文&#xff08;不加密&#xff09;&#xff0c;内容可能会被窃听 不验证通信方的身份&#xff0c;可能遭遇伪装 无法证明报文的完整性&#xff0c;所以有可能遭篡改 一、通信使用明文&#xff08;不加密&#xff09;&#xff0c;内容可能会被窃听 TCP/…

鸿蒙OpenHarmony【轻量系统 编译】 (基于Hi3861开发板)

编译 OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式&#xff0c;build.sh脚本编译方式请参考[使用build.sh脚本编译源码]。 使用build.sh脚本编译源码 进入源码根目录&#xff0c;执行如下命令进行版本编译。 ./build.sh --product-name name --ccache 说明&…

【算法基础实验】图论-深度优先搜索和深度优先路径

深度优先(DFS) 理论基础 深度优先搜索&#xff08;DFS, Depth-First Search&#xff09;是图和树的遍历算法中的一种&#xff0c;它从一个节点开始&#xff0c;沿着树的边走到尽可能深的分支&#xff0c;直到节点没有子节点为止&#xff0c;然后回溯继续搜索下一个分支。DFS …

python基础之元组、集合和函数的定义与返回值

1.元祖 1.元祖的定义 元组的数据结构跟列表相似 特征&#xff1a;有序、 有序&#xff1a;有&#xff08;索引/下标/index&#xff09; 正序、反序标识符&#xff1a; ( ) 里面的元素是用英文格式的逗号分割开来关键字&#xff1a;tuple 列表和元组有什么区别&#xff1f; 元组…

JavaEE 初阶篇-深入了解 I/O 高级流(缓冲流、交换流、数据流和序列化流)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 缓冲流概述 1.1 缓冲流的工作原理 1.2 使用缓冲流的步骤 1.3 字节缓冲流于字符缓冲流的区别 1.4 字节缓冲流的实例 1.5 字符缓冲流的实例 2.0 转换流概述 2.1 字符…

局部多项式近似与 AMPM 算法

kappa3; %已在您的代码中定义% 定义窗口大小 windowSize (2*kappa1);% 初始化梯度估计值 [rows, cols] size(wrappedPhase); phi_y zeros(rows, cols); phi_x zeros(rows, cols);% 遍历每个窗口 for m 1kappa:rows-kappafor n 1kappa:cols-kappa% 提取局部窗口Z_mn wrap…

Git--基础学习--面向企业--持续更新

一、基础学习 1.1基本命令 //查询基础信息 git config --global --list //选取合适位置创建 mkdir 文件名 //创建文件夹 //全局配置 git config --global user.email "****e***i" git config --global user.name "*** K****"//--------------------进入…
最新文章