每日一题——力扣27. 移除元素(举一反三)

题目链接:https://leetcode.cn/problems/remove-element/description/

 

菜鸡写法:

// 函数定义,移除数组nums中所有值为val的元素,并返回新的数组长度
int removeElement(int* nums, int numsSize, int val) {// 如果数组长度为0,直接返回0if (numsSize == 0) {return 0;}// 初始化两个指针,left指向数组的开始,right指向数组的末尾int left = 0, right = numsSize - 1;// 初始化一个变量来记录值为val的元素数量int num_of_val = 0;// 初始化一个临时变量用于交换元素int tmp;// 如果数组只有一个元素if (left == right) {// 如果这个元素的值等于val,则将数组指针置为NULL,并返回0if (*(nums + left) == val) {nums = NULL;return 0;} else {// 否则返回1,因为数组中没有需要移除的元素return 1;}}// 开始遍历数组,直到left指针超过right指针for (; left < right;) {// 如果left指向的元素等于val,且right指向的元素不等于valif (*(nums + left) == val && *(nums + right) != val) {// 增加值为val的元素计数num_of_val += 1;// 交换left和right指向的元素tmp = *(nums + left);*(nums + left) = *(nums + right);*(nums + right) = tmp;// 移动left和right指针left += 1;right -= 1;} else {// 如果left指向的元素不等于val,则移动left指针if (*(nums + left) != val) {left += 1;}// 如果right指向的元素等于val,则增加计数并移动right指针if (*(nums + right) == val) {num_of_val += 1;right -= 1;}}}// 如果left和right指针相遇,且指向的元素等于valif (left == right && *(nums + left) == val) {// 将该元素移到数组的末尾,并增加计数for (; left <= numsSize - num_of_val - 2; left++) {*(nums + left) = *(nums + left + 1);}num_of_val += 1;}// 返回新的数组长度,即原数组长度减去值为val的元素数量return numsSize - num_of_val;
}

这段代码实现了移除数组中指定值的功能,其核心思想是使用双指针技术,一个指针从数组头开始,另一个从数组尾开始,通过交换元素的方式将所有值为val的元素移到数组的末尾。下面是对这段代码的点评:

代码结构与逻辑

  • 初始化:代码首先检查数组长度是否为0,如果是,则直接返回0。然后初始化两个指针leftright,分别指向数组的开始和末尾。
  • 单元素处理:对于只有一个元素的数组,代码进行了特殊处理,如果该元素等于val,则将数组指针置为NULL并返回0,否则返回1。
  • 双指针遍历:代码使用双指针遍历数组,如果left指向的元素等于valright指向的元素不等于val,则交换这两个元素,并移动指针。如果left指向的元素不等于val,则只移动left指针;如果right指向的元素等于val,则只移动right指针。
  • 边界情况处理:当leftright指针相遇时,如果指向的元素等于val,则将该元素移到数组的末尾。
  • 返回结果:最后,代码返回新的数组长度,即原数组长度减去值为val的元素数量。

时间复杂度分析

  • 最坏情况:在最坏的情况下,即数组中所有的元素都等于val,此时需要遍历整个数组,因此时间复杂度为O(n),其中n是数组的长度。
  • 最好情况:在最好的情况下,即数组中没有元素等于val,此时只需要遍历一次数组,时间复杂度同样为O(n)。

空间复杂度分析

  • 额外空间:代码只使用了常数级别的额外空间,包括用于交换元素的临时变量tmp和用于计数的变量num_of_val,因此空间复杂度为O(1)。

改进建议

  • 指针移动逻辑:在双指针遍历的过程中,代码中的指针移动逻辑可以进一步优化,以减少不必要的判断和操作。例如,可以直接在交换元素的同时移动指针,而不需要额外的判断。
  • 边界处理:对于leftright指针相遇时的处理,可以考虑直接在遍历过程中处理,而不是在遍历结束后单独处理。
  • 返回数组指针:如果需要返回修改后的数组指针,可以考虑在函数中返回,而不是仅仅返回新的数组长度。

总体来说,这段代码实现了移除数组中指定值的功能,具有较好的时间复杂度和空间复杂度,但在代码逻辑和边界处理上还有一定的优化空间。
 

双指针优化法:
 

int removeElement(int* nums, int numsSize, int val) {// 初始化两个指针,`i` 用于遍历数组,`j` 用于记录新数组的长度int i = 0, j = 0;// 遍历整个数组for (i = 0; i < numsSize; i++) {// 如果当前元素不等于 `val`if (nums[i] != val) {// 将当前元素移动到新数组的位置 `j`nums[j] = nums[i];// 更新新数组的长度j++;}}// 返回新数组的长度return j;
}

逐行注释解释:

  1. int i = 0, j = 0;:初始化两个指针,i 用于遍历数组,j 用于记录新数组的长度。
  2. for (i = 0; i < numsSize; i++) {:开始遍历数组,i 从0开始,直到数组的长度。
  3. if (nums[i] != val) {:检查当前元素是否不等于 val
  4. nums[j] = nums[i];:如果当前元素不等于 val,将其移动到新数组的位置 j
  5. j++;:更新新数组的长度,即 j 指针向前移动一位。
  6. return j;:遍历结束后,返回新数组的长度。

时间复杂度和空间复杂度:

  • 时间复杂度:O(n),其中 n 是数组的长度。我们只需要遍历一次数组。
  • 空间复杂度:O(1),我们只使用了常数级别的额外空间。

改进建议:

这段代码已经很高效,没有明显的改进空间。它简洁、直观地实现了移除数组中指定值的功能,同时保持了较低的时间和空间复杂度。
 

该方法体现了以下哲学和编程思想:

  1. 简洁性(Simplicity):代码力求简洁明了,避免不必要的复杂性。通过使用两个指针,代码直接实现了移除指定值的功能,没有引入额外的数据结构或复杂的逻辑。

  2. 效率(Efficiency):双指针方法在时间复杂度上达到了O(n),这意味着它只需要遍历一次数组,是一种非常高效的处理方式。同时,空间复杂度为O(1),表明代码只使用了常数级别的额外空间,符合空间效率的要求。

  3. 迭代(Iteration):代码通过迭代的方式遍历数组,这是一种常见的编程模式,用于处理数组、列表等线性数据结构。迭代允许我们逐步处理数据,而不是一次性处理,这有助于提高代码的可读性和可维护性。

  4. 指针操作(Pointer Manipulation):在C语言中,指针是一种强大的工具,可以直接操作内存。双指针方法巧妙地利用了指针来跟踪数组中的元素,这是一种低级别的编程技巧,体现了对内存管理的深刻理解。

  5. 条件逻辑(Conditional Logic):代码中使用了条件语句(if)来决定是否将当前元素添加到新数组中。这种基于条件的逻辑是编程中的基本思想,用于根据不同的情况执行不同的操作。

  6. 增量式开发(Incremental Development):虽然代码本身很简洁,但在开发过程中,程序员可能会逐步添加功能,测试每个部分,确保代码的正确性。这种增量式的开发方法有助于减少错误,提高代码质量。

  7. 算法思维(Algorithmic Thinking):双指针方法是一种特定的算法,用于解决特定类型的问题。这种思维方式要求程序员能够识别问题的模式,并设计出有效的解决方案。

  8. 抽象(Abstraction):代码抽象了移除数组中指定值的逻辑,使得其他开发者可以不关心具体的实现细节,直接使用这个函数来完成任务。

举一反三

基于双指针方法的思想和应用,以下是一些技巧和原则,可以帮助你在其他编程任务中举一反三:

1. 空间优化

  • 原地操作:尽可能在输入的数据结构上直接进行修改,减少额外空间的使用。例如,在排序、合并或修改数组和链表时,考虑是否可以通过调整元素位置而不是创建新的数据结构来实现。

2. 时间优化

  • 单遍扫描:设计算法时,尽量确保只需要遍历数据一次。多数使用双指针的场景,如去除重复项、查找对应和等,都是基于只遍历一遍数据来实现的。

3. 思维模式

  • 对撞指针:在排序数组或链表中寻找两个数的和等特定问题时,可以从两端开始遍历,根据条件向中间逼近。
  • 快慢指针:用于解决循环链表的判断、查找中间节点等问题。快指针的移动速度是慢指针的两倍,通过它们的相对速度差来解决问题。

4. 抽象思维

  • 泛化问题解决方案:学习双指针技巧的同时,思考其背后的原理,例如减少不必要的遍历、空间优化等。这些原理不仅仅适用于数组和链表,也可以扩展到其他数据结构和问题上。

5. 条件逻辑与增量思想

  • 逐步构建解决方案:在解决问题时,从最简单的情况开始,逐渐添加条件和逻辑,以构建完整的解决方案。这有助于避免一开始就陷入复杂的情况,使问题更易于理解和解决。
  • 灵活应用条件判断:在使用双指针技巧时,根据问题的需求调整指针的移动条件。例如,满足某条件时移动左指针,不满足时移动右指针,或者两者都移动。

6. 代码优化与重构

  • 迭代与重构:在初步实现功能后,通过测试和验证来识别性能瓶颈或不必要的复杂度,然后迭代优化。这可能涉及调整算法、简化逻辑或利用更高效的数据结构。

通过掌握这些技巧和原则,你可以将双指针方法背后的思想应用到更宽泛的编程问题和数据结构上,提高代码的效率和质量。记住,好的编程实践不仅仅是关于解决一个特定问题,而是学会如何以一种可扩展、可维护的方式思考和实现解决方案。

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

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

相关文章

【智能优化算法】金豺狼优化算法(Golden jackal optimization,GJO)

金豺狼优化(Golden jackal optimization,GJO)是期刊“Expert Systems with Applications”&#xff08;中科院一区IF 8.3&#xff09;的2022年智能优化算法 01.引言 金豺狼优化(Golden jackal optimization,GJO)旨在为解决实际工程问题提供一种替代的优化方法。GJO的灵感来自金…

c++:(map和set的底层简单版本,红黑树和AVL树的基础) 二叉搜索树(BST)底层和模拟实现

文章目录 二叉搜索树的概念二叉搜索树的操作二叉搜索树的查找find 二叉搜索树的模拟实现构造节点insertfinderase(细节巨多,面试可能会考)a.叶子节点b.有一个孩子左孩子右孩子 c.有两个孩子注意: erase代码 中序遍历 二叉搜索树的应用k模型k模型模拟实现的总代码 k-value模型k-…

高校教务选课管理系统开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 随着高校教育规模的扩大&#xff0c;教务管理变得越来越复杂&#xff0c;传统的手工管理方式已经无法满足现代高校的需求。因此&#xff0c;开发一套高效、便捷的高校教务选课管理系统显得尤为重要。该系统将涵盖学生…

基于Springboot+Vue的Java项目-车辆管理系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

公司活动想找媒体报道宣传怎样联系媒体?

作为公司宣传负责人,我深知媒体报道对于企业活动宣传的重要性。然而,在过去,每当有重要活动需要媒体曝光时,我总会被繁琐的媒体联系工作所困扰。 那时,我需要一家家地查询媒体联系方式,发送邮件、打电话,甚至亲自前往媒体机构进行沟通。然而,这样的过程不仅费时费力,而且效率低…

C++ 抽象与封装

一 抽象 抽象实例&#xff1a;时钟 数据抽象&#xff1a; 具有表面当前时间的时、分、秒 行为抽象&#xff1a; 具有设置时间和显示时间两个最基本的功能。 抽象实例&#xff1a;人 数据抽象&#xff1a;姓名、年龄、性别等。 行为抽象&#xff1a; 生物属性&#xff1a;吃…

宏集Panorama SCADA软件获BACnet BTL认证

Panorama 获得BACnet BTL认证 建筑物的组件&#xff08;空调系统、照明传感器等&#xff09;能否使用共同通讯协议&#xff1f;这正是标准化 BACnet协议&#xff08;Building Automation and Control Networks&#xff09;所提供的功能。该协议旨在实现建筑物中各种设备和系统…

更新、简略高效的用git(Gitee篇)

前提&#xff1a;因为很多编译软件虽然可以连接git&#xff0c;但是操作起来还是比较懵&#xff0c;不同软件有不同的上传git的方式&#xff0c;而且有的连着GitHub有的是Gitee&#xff0c;那么使用Git Bash无疑是万无一失的方式 然后这一篇也仅针对上传Gitee&#xff0c;上传G…

【C++】学习笔记——优先级队列

文章目录 十、优先级队列1. priority_queue的介绍2. 优先级队列如何使小的数据优先级高3. 仿函数介绍4. priority_queue的模拟实现 补&#xff1a; 反向迭代器未完待续 十、优先级队列 1. priority_queue的介绍 优先级队列 其实也不属于队列&#xff0c;它跟 stack 和 queue …

【智能优化算法】卷尾猴搜索算法(Capuchin search algorithm,CapSA)

【智能优化算法】卷尾猴搜索算法(Capuchin search algorithm,CapSA)是期刊“NEURAL COMPUTING & APPLICATIONS”&#xff08;IF 6.0&#xff09;的2021年智能优化算法 01.引言 【智能优化算法】卷尾猴搜索算法(Capuchin search algorithm,CapSA)用于解决约束和全局优化问…

Ubuntu 安装 samba 实现文件共享

1. samba的安装: sudo apt-get install samba sudo apt-get install smbfs2. 创建共享目录 mkdir /home/share sudo chmod -R 777 /home/share3. 创建Samba配置文件: 3.1 保存现有的配置文件 sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak3.2 打开现有的文件 sudo…

安卓开发--按键跳转页面

前面已经介绍了一个空白按键工程的建立以及响应方式&#xff0c;可以参考这里&#xff1a;安卓开发–新建工程&#xff0c;新建虚拟手机&#xff0c;按键事件响应。 安卓开发是页面跳转是基础&#xff01;&#xff01;&#xff01;所以本篇博客介绍利用按键实现页面跳转。 前…

解锁楼宇自动化新维度西门子Insight+BACnet IP I/O控制器

数字城市的楼宇自动化已不再是一个遥不可及的概念&#xff0c;而是成为了现代建筑的标配。特别是在大型商业综合体、高端写字楼和公共设施中&#xff0c;高效的楼宇管理系统是确保环境舒适度与能源效率的关键。当提及楼宇自动化领域的佼佼者&#xff0c;西门子Insight楼宇自动化…

15 华三华为链路聚合综述

1 链路聚合简介 以太网链路聚合通过将多条以太网物理链路捆绑在一起形成一条以太网逻辑链路&#xff0c;实现增加链路带宽的目的&#xff0c;同时这些捆绑在一起的链路通过相互动态备份&#xff0c;可以有效地提高链路的可靠性。 2 成员端口的状态 聚合组内的成员端口具有以下…

Android 屏幕适配全攻略(中)-从九宫格到矢量图,揭秘Android多屏幕适配的正确打开方式

在移动互联网时代&#xff0c;无论是小小的手机屏幕&#xff0c;还是大大的平板显示器&#xff0c;Android 应用都必须做到完美适配&#xff0c;给用户以极佳的体验。本文将剖析 Android 多屏幕适配背后的种种技术细节&#xff0c;为您揭开最佳实践的正确打开方式&#xff0c;让…

全新时代的降临——比亚迪,助力未来出行

近日&#xff0c;世界舞台中央聚焦&#xff0c;比亚迪登上欧洲顶级赛事赞助席位&#xff0c;让全球见证中国新能源汽车传奇崛起&#xff01;作为新能源领袖品牌&#xff0c;比亚迪现已累计销售突破730万辆&#xff0c;全球每售出五辆新能源汽车&#xff0c;便有一辆来自比亚迪。…

基于Springboot的微乐校园管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的微乐校园管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

什么是季节调整?

季节调整是指在对时间序列分析过程中估计和剔除季节因素的一种方法。 一、基本概念 在分析应用中发现&#xff0c;一个经济时间序列往往受多种因素影响&#xff0c;通常我们把这些因素分为趋势因素、循环因素、季节因素、以及不规则因素。其中&#xff0c;季节因素是指时间序…

软考中级-软件设计师(九)数据库技术基础 考点最精简

一、基本概念 1.1数据库与数据库系统 数据&#xff1a;是数据库中存储的基本对象&#xff0c;是描述事物的符号记录 数据库&#xff08;DataBase&#xff0c;DB&#xff09;&#xff1a;是长期存储在计算机内、有组织、可共享的大量数据集合 数据库系统&#xff08;DataBas…

Hive Windows Functions 窗口函数

Hive Windows Functions 窗口函数 在 Hive 中&#xff0c;窗口函数&#xff08;Window Functions&#xff09;用于在查询结果中执行聚合、排序和分析操作&#xff0c;而无需将数据分组。窗口函数允许你在查询结果中的一组行上执行计算&#xff0c;而不会改变原始数据的行数&am…