当前位置: 首页 > news >正文

每日两道力扣,day5

每日两道力扣,day5

每日两道力扣,day5

每日两道力扣,今日是:

27. 移除元素 - 力扣(LeetCode)

283. 移动零 - 力扣(LeetCode)

第一题:移除元素

27. 移除元素 - 力扣(LeetCode)

1.思路:

这是代码随想录上的一道双指针算法模板题。

(1)我们先尝试暴力的方法,利用两个for循环,我们可以很好地解决这个题目。第一个for循环,用来控制数组的左端的变化,第二个for循环用来通过遍历去移除元素。只要第一个循环里的nusm[i] == val,咱们就在第二个循环里移除元素。时间复杂度O(n^2),尽管能跑过,但显然不是最优解。

(2)为了探寻最优解,我们将引入双指针算法。这将是我们算法旅程中的好伙伴,在数组,链表,栈等等情景里面,都常常会有他的身影。暴力法运用了两个for循环,那我们可以通过双指针降维打击,只采用一个for循环解决问题。首先初始化两个指针,slow,fast为0。快指针fast先跑,用来查找数组里面值不为val的元素,找到后,利用slow和fast更新数组,循环结束后,返回的slow的大小,就是题目的解。时间复杂度为O(n)。

2.代码实现:

(1)方法一:(暴力)

class Solution { public: int removeElement(vector<int>& nums, int val) { int n = nums.size(); for(int i = 0; i < n; i++) { if(nums[i] == val) { for(int j = i + 1; j < n; j++) { nums[j - 1] = nums[j]; } //因为此时,下标i以后的元素都往前移动了一位,为了确保不发生遗漏的情况,i也得往前移动一位 i--; //移除了一个元素,数组大小减1 n--; } } return n; } };

(2)方法二:(双指针)

class Solution { public: int removeElement(vector<int>& nums, int val) { int slow = 0; for(int fast = 0; fast < nums.size(); fast++) { if(val != nums[fast]) { nums[slow++] = nums[fast]; } } return slow; } };
3.细节

这个题比较简单,没有什么细节可注意的。

第二题:移动零

283. 移动零 - 力扣(LeetCode)

1.思路:

这道题是一道典型的双指针模板题。我们可以想移除元素那样采用快慢指针,其中快指针fast用来寻找不为0的元素。找到后利用swap交换nums[slow],nums[fast]。

2.代码实现:
class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0, n = nums.size(); for(int fast = 0; fast < n; fast++) { if(nums[fast] != 0) { swap(nums[slow], nums[fast]); slow++; } } } };
3.细节:

尽管写出来了,但我们看到题目的进阶提问 **进阶:**你能尽量减少完成的操作次数吗?不免疑惑,我们使用双指针算法已经很完美了,还有哪里可以优化的地方呢?如果面试官在算法面问道你这个问题时,你该怎么办?

破案:当前代码在哪里浪费了操作次数?

在 C++ 中,一次swap(a, b)函数的底层运行其实包含了3 次赋值操作

  1. int temp = a;
  2. a = b;
  3. b = temp;

现在想象一个极端的测试用例:数组里根本没有 0,比如[1, 2, 3, 4, 5]。 你的代码会怎么跑?

  • fast遇到1,非零。执行swap(nums[0], nums[0])。自己和自己交换(白白浪费 3 次赋值)。
  • fast遇到2,非零。执行swap(nums[1], nums[1])。(又浪费 3 次赋值)。

如果数组有 10000 个非零元素,你的代码就会做30000 次没有意义的自我赋值操作!

为了解决这个问题,我们有两种优化方向。

第一种:打个补丁

既然问题出在“自己和自己交换”上,那我们加个判断:只有当fastslow不在同一个位置时,才进行交换。

class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0, n = nums.size(); for(int fast = 0; fast < n; fast++) { if(nums[fast] != 0) { // 优化点:如果不重合才交换,避免全是非0元素时的自我交换 if (slow != fast) { swap(nums[slow], nums[fast]); } slow++; } } } };

效果:遇到[1, 2, 3, 4, 5]这样的纯非零数组时,操作次数直接降为0 次交换

第二种:“覆盖 + 填坑” 法

swap始终太贵了(3 次赋值)。如果不追求“实时把 0 换到后面”,我们可以采取**“两步走”**的策略:

第一步(覆盖):只管把非 0 的数字一股脑儿往前面扔。遇到非 0 的,直接覆盖到slow的位置。单次覆盖只需1 次赋值第二步(填坑):当前面都被非 0 数字占满后,slow往后的位置本来应该都是 0。我们直接写个循环,把后面的全填成 0 就行了。

class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0, n = nums.size(); // 步骤 1:把所有非 0 元素统统往前覆盖 for (int fast = 0; fast < n; fast++) { if (nums[fast] != 0) { // 直接覆盖,不用 swap。只需 1 次赋值操作! nums[slow] = nums[fast]; slow++; } } // 步骤 2:此时所有的非 0 元素都已经按顺序排在前面了 // slow 指向的及后面的位置,全该是 0,我们自己手动填平 for (int i = slow; i < n; i++) { nums[i] = 0; } } };

为什么方案 2 更好?(算一笔账)

假设数组是[1, 2, 3, 4, 0](大部分是非零元素):

  • 你的原版代码:1,2,3,4各发生一次swap。总赋值次数 = 4 * 3 =12 次
  • “覆盖 + 填坑”法:1,2,3,4各被提取覆盖一次(4 次)。最后给末尾补一个 0(1 次)。总赋值次数 =5 次

结论:当数组中的非零元素较多时,方案 2(覆盖填坑法)能极大地减少操作次数,这也是 LeetCode 官方题解和高级面试中最被推崇的“操作数最少”解法。

好了,今天的每日两道力扣到这里就算是结束了,看完是不是感觉有所收获呢?如果学有所获的话,麻烦给个三连支持一下呗。感谢观看,您的支持,将是我前进路上的重要动力。

http://www.cnnetsun.cn/news/1744675.html

相关文章:

  • OpenClaw配置优化:Qwen3.5-9B-AWQ-4bit模型参数调优实战
  • java新手福音,用快马ai生成你的第一份个性化学习路线与练习项目
  • 提升教程制作效率,快马平台ai助你自动生成python入门示例与习题
  • Diablo Edit2:开源工具带来的暗黑破坏神II游戏体验优化
  • 不只是导入:在Android原生App中深度定制Unity启动流程与界面融合
  • Windows Subsystem for Android开源项目配置指南:从环境搭建到性能优化全攻略
  • 数据可视化实战:AntV与ECharts图表选型指南
  • Cogito-V1-Preview-Llama-3B能力展示:C语言基础教学与代码纠错
  • Masa Mods中文界面终极指南:3分钟让Minecraft模组变中文,轻松掌握建筑神器
  • JAVA校园招聘类型小程序APP实现原理开源代码
  • 语雀文档本地化:从平台依赖到数据自主的全流程解决方案
  • 3步轻松搞定网络资源获取:猫抓浏览器扩展零基础入门指南
  • 修改文件的创建日期和修改日期,5款工具,小白零出错不加班
  • 告别环境配置噩梦:用Docker Desktop + WSL2在Windows上5分钟搞定vLLM运行环境
  • 第二章 基本放大电路
  • MVP.css跨浏览器兼容性终极指南:7个实用技巧解决常见问题
  • Tessent测试流程文件里的Tcl魔法:用if/else让你的扫描测试配置更灵活
  • 如何构建强大的开源社区:PocketBase项目维护与用户支持完整指南
  • rabbitmq新手福音,快马ai生成带详解注释的入门代码,轻松理解消息队列
  • 51单片机没有硬件SPI?别慌!手把手教你用普通IO口模拟SPI驱动OLED屏幕(附完整代码)
  • 老旧设备联网改造方案:用RJ45串口服务器实现PLC远程监控(附避坑清单)
  • 基于Web BLE API的智能设备双向通信实战
  • 第7章 运算符-7.6 成员运算符
  • 打破限速潜规则的技术偏方:让八大云盘下载速度飞起来的秘密武器
  • 如何在5分钟内搭建专属的Galgame视觉小说社区:TouchGAL完全指南
  • 10个SQL高级特性完全解析:db-tutorial教你写出高效查询的终极指南
  • Harness十篇博客
  • G-Helper终极指南:如何用免费开源工具完美控制你的华硕游戏本
  • Python实战:用GDAL给大疆御3E照片添加WGS-84坐标系(附完整代码)
  • PotPlayer字幕翻译插件终极指南:5分钟实现外语视频无障碍观看