LeetCode 第26题:删除有序数组中的重复项
1.LeetCode 第10题:正则表达式匹配2.LeetCode 第1题:两数之和3.LeetCode 第2题:两数相加4.LeetCode 第3题:无重复字符的最长子串5.LeetCode 第4题:寻找两个正序数组的中位数6.LeetCode 第8题:字符串转换整数 (atoi)7.LeetCode 第7题:整数反转8.LeetCode 第6题:Z字形变换9.LeetCode 第5题:最长回文子串10.LeetCode 第9题:回文数11.LeetCode 第11题:盛最多水的容器12.LeetCode 第12题:整数转罗马数字13.LeetCode 第13题:罗马数字转整数14.LeetCode 第14题:最长公共前缀15.LeetCode 第15题:三数之和16.LeetCode 第16题:最接近的三数之和17.LeetCode 第17题:电话号码的字母组合18.LeetCode 第18题:四数之和19.LeetCode 第19题:删除链表的倒数第N个结点20.LeetCode 第20题:有效的括号21.LeetCode 第21题:合并两个有序链表22.LeetCode 第22题:括号生成23.LeetCode 第23题:合并K个升序链表24.LeetCode 第24题:两两交换链表中的节点25.LeetCode 第25题:K 个一组翻转链表
26.LeetCode 第26题:删除有序数组中的重复项
27.LeetCode 第27题:移除元素28.LeetCode 第28题:找出字符串中第一个匹配项的下标29.LeetCode 第29题:两数相除30.LeetCode 第30题:串联所有单词的子串31.LeetCode 第31题:下一个排列32.LeetCode 第32题:最长有效括号33.LeetCode 第33题:搜索旋转排序数组34.LeetCode 第34题:在排序数组中查找元素的第一个和最后一个位置35.LeetCode 第35题:搜索插入位置36.LeetCode 第36题:有效的数独37.LeetCode 第37题:解数独38.LeetCode 第38题:外观数列39.LeetCode 第39题:组合总和40.LeetCode 第40题:组合总和 II41.LeetCode 第41题:缺失的第一个正数LeetCode 第26题:删除有序数组中的重复项
题目描述
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
难度
简单
题目链接
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
示例
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4,_,_,_,_,_]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示
- 1 <= nums.length <= 3 * 104
- -104 <= nums[i] <= 104
- nums 已按 升序 排列
解题思路
方法:双指针
使用快慢指针的方法,慢指针指向当前已处理好的数组的最后一个位置,快指针用于遍历数组。
关键点:
- 数组已经排序,相同元素相邻
- 使用快慢指针处理
- 原地修改数组
- 保持相对顺序
具体步骤:
- 如果数组为空,返回0
- 初始化慢指针slow = 0
- 使用快指针fast遍历数组:
- 如果nums[fast] != nums[slow],说明遇到新元素
- 将slow指针前进一位,并将新元素复制到slow位置
- 返回slow + 1(新数组的长度)
时间复杂度:O(n),其中n是数组的长度
空间复杂度:O(1)
代码实现
C# 实现
public class Solution {
public int RemoveDuplicates(int[] nums) {
if (nums == null || nums.Length == 0) return 0;
int slow = 0;
for (int fast = 1; fast < nums.Length; fast++) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
}
代码详解
- 边界检查:
- 处理空数组和长度为0的情况
- 双指针使用:
- slow指针指向当前不重复序列的最后位置
- fast指针用于遍历数组寻找新元素
- 数组修改:
- 只在找到新元素时修改数组
- 保证原地修改且空间复杂度为O(1)
执行结果
- 执行用时:124 ms
- 内存消耗:44.1 MB
总结与反思
- 这是一道经典的数组处理题目:
- 考察双指针技巧
- 考察原地修改数组
- 考察空间效率
- 解题要点:
- 利用数组已排序的特性
- 使用双指针降低时间复杂度
- 原地修改避免额外空间
- 优化思路:
- 可以添加快速判断相邻元素
- 考虑特殊情况的优化
- 注意边界条件的处理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了