Leetcode刷题笔记之数组篇26. 删除有序数组中的重复项

Posted 大家好我叫张同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode刷题笔记之数组篇26. 删除有序数组中的重复项相关的知识,希望对你有一定的参考价值。

😈博客主页:🐼大家好我叫张同学🐼
💖 欢迎点赞 👍 收藏 💗留言 📝 欢迎讨论! 👀
🎵本文由 【大家好我叫张同学】 原创,首发于 CSDN 🌟🌟🌟
精品专栏(不定时更新) 【数据结构+算法】 【做题笔记】【C语言编程学习】
☀️ 精品文章推荐
【C语言进阶学习笔记】三、字符串函数详解(1)(爆肝吐血整理,建议收藏!!!)
【C语言基础学习笔记】+【C语言进阶学习笔记】总结篇(坚持才有收获!)
【Linux编程】一、Linux常见指令和权限理解(思维导图总结)


前言

为什么要写刷题笔记
写博客的过程也是对自己刷题过程的梳理总结,是一种耗时有效的方法。
当自己分享的博客帮助到他人时,又会给自己带来额外的快乐和幸福。
(刷题的快乐+博客的快乐,简直是奖励翻倍,快乐翻倍有木有QAQ🙈)

题目内容

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有k个元素,那么nums的前 k个元素应该保存最终结果。 将最终结果插入nums的前 k个位置后返回 k
不要使用额外的空间,你必须在 原地修改输入数组 并在使用O(1) 额外空间的条件下完成。


原题链接(点击跳转)

解题过程

要想保留非重复项,我们可以采取的一种方式,就是每次都遍历一次前面的数组元素
1)如果不出现重复的,就将其保留到数组当中。
2)如果出现重复的就跳过该元素。这种方式对于有序以及非有序的数组均适用。


时间复杂度为O(N^2),空间复杂度为O(1)

【C语言版】

int removeDuplicates(int* nums, int numsSize)
    int cur = 0,prev = 0;//保留当前的和上一个的数组下标
    for(cur = 0;cur<numsSize;++cur)
    
        int flag = 1;//设置一个标签来记录当前元素cur是否跟前面的元素重复,默认1表示不重复
        for(int i = 0;i<cur;++i)
        
            if(nums[i] == nums[cur])
                flag = 0;//如果出现重复就将标签flag改为0
        
        if(flag == 1)//只有当标签为1的时候,才将cur元素放到数组中
           nums[prev++] = nums[cur];
    
    return prev;//最终prev代表的就是数组中元素的个数


【C++版】

class Solution 
public:
    int removeDuplicates(vector<int>& nums) 
        int cur = 0,prev = 0;
        for(cur = 0;cur < nums.size();++cur)//用nums.size()来获取数组的长度
        
            int flag = 1;
            for(int i = 0;i < cur;++i)
            
                if(nums[i] == nums[cur])
                  flag = 0;
            
            if(flag == 1)
              nums[prev++] = nums[cur];
        
        return prev;
    
;

可以看到用C语言可以通过测试,但是内存耗时是比较长的,用C++就更加明显,根本就通过不了测试,超出时间限制了。


思路优化

考虑到目前数组中的元素已经按照升序排列了,那么重复的元素一定是紧挨着放的,比如 1 1 2 3 3 4 7,1和1、3和3 都是紧挨着的。所以我们可以考虑用双下标+虚拟数组的方式来处理这个问题。假设有两个下标prev、cur,cur往后遍历,如果cur所在元素和prev不一样,就将其给到prev,然后继续向后遍历,如果cur和prev一样,那就直接跳过这个元素。

假设输入:nums = [0,0,1,1,1,2,2,3,3,4]

prev从第一个元素开始,cur要从第二个元素开始,如果数组的元素个数小于两个,直接返回数组,因为这种情况下,不可能存在重复元素

当下标cur和prev元素相同时,cur直接往后走

当cur和prev指向元素不相同时,先让prev往后走一步,然后将cur的元素给到prev,然后cur再往后走一步

cur指向的两个1和prev相同,跳过,到达2的位置

先让prev移动到下一个位置,然后将cur指向的2给到prev,然后cur再往后走一步

直到cur遍历完整个数组结束。


【完整的算法图解】

【C语言版】

int removeDuplicates(int* nums, int numsSize)
    if(numsSize < 2)//如果数组的元素小于2个,就不可能存在重复元素,直接返回
       return numsSize;
    int prev = 0,cur = 1;//prev从第一个元素开始,cur从第二个元素开始
    while(cur < numsSize)
    
        if(nums[cur] != nums[prev])//如果cur指向元素和prev不一样
        
            nums[++prev] = nums[cur++];//先让prev向后走一步,然后将cur元素给到prev,之后cur再向后走一步
        
        else
        
            ++cur;//如果cur和prev元素相同,直接跳过该元素,cur直接向后走一步
        
    
    return prev + 1;//最终prev指向最后一个元素的下标,元素个数等于prev+1


【C++版】

class Solution 
public:
    int removeDuplicates(vector<int>& nums) 
        if(nums.size() < 2)//如果元素小于2个,直接返回
           return nums.size();
        int prev = 0,cur = 1;
        while(cur < nums.size())
        
            if(nums[cur] == nums[prev])
               ++cur;
            else
               nums[++prev] = nums[cur++];
        
        return prev + 1;
    
;

以上是关于Leetcode刷题笔记之数组篇26. 删除有序数组中的重复项的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题笔记之数组篇26. 删除有序数组中的重复项

算法进阶之Leetcode刷题记录

LeetCode 解题笔记数组篇

leetcode刷题系列 26题 删除排序数组中的重复项

Leetcode刷题100天—26. 删除有序数组中的重复项(数组)—day76

Leetcode刷题100天—26. 删除有序数组中的重复项(数组)—day76