C语言数据结构-删除数组中的重复项

1.题目描述:

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array


2.编程思路:

        对于数据结构题目的编程思路,我建议大家直接画图,画图能够帮助我们更全面地思考问题。首先明确目标是删除有序(升序)数列的重复项。如果我们不考虑时间和空间复杂度,那么最先想到的就是方法1——遍历删除。也就是定义两个序号Start从0开始、End从1开始,如果两者指向的元素相等就说明有重复数据出现,然后将End和以后的数据都向前挪动,直到End指向数组的最后一个元素,如图1所示。

C语言数据结构-删除数组中的重复项_第1张图片

图1

       这种方法能够完成功能,但是并不能满足要求,因为时间复杂度为O(n^2)。所谓时间复杂度就是执行简单代码的次数,上述方法在最坏的情况下(全部都是一样的数据)需要移动(也就是值覆盖)n-1、n-2、...、2、1,利用等差数列求和可以求出一共需要有n*(n-1)/2次赋值操作,所以时间复杂度就是O(n^2)。没有开辟新的空间,所以空间复杂度是O(1)。

       方法2:我们重新开辟一个数组,也用两个序号进行操作,Src遍历指向原数组,Dst遍历指向新开辟的数组。不同的是,我们不移动后面的所有值,而是只要Src和Dst所指向的数据不同就将Src所指向的数据赋给Dst所指向的空间,这里的细节一定要注意,谁走在前面,谁赋值给谁。如图2所示。

C语言数据结构-删除数组中的重复项_第2张图片

 图2

      这种方法也能实现功能,但是空间复杂度是O(n),不能满足要求。

        方法3:我们可以从上面两种简单粗暴的方法中吸取优点,就是让两个序号去遍历,最后将满足条件的的值赋给自己,也就是数组内的值覆盖。如图3所示,我们让Start和End两个序号去遍历原数组,如果两个不等就将Start所指向的数据赋给Dst所指向的空间,这也是所谓的三指针,但是成作序号更好理解。这里有一个细节就是会有End越界的时候,这时候就有最后两个数是相等还是不等两种情况,但是不管是哪种情况都应该把Start所指向的数据赋给Dst所指向的空间。(这点大家画图好好想一下,虽然简单,但是是细节!)

C语言数据结构-删除数组中的重复项_第3张图片

 图3

        时间复杂度:这个相当于执行n次条件赋值操作,所以就是O(n),空间复杂度为O(1)。

3.代码

int removeDuplicates(int* nums, int numsSize){
    // 处理空数组整个特殊情况
    if(numsSize == 0)
    {
        return 0;   
    }
    // 定义三个序号
    int Start = 0;
    int End = 1;
    int Dst = 0;
    while(End

4.总结

        对于C语言的数据结构,最重要的就是画图(这能够帮助理清逻辑)、分析复杂度、敲代码!


你可能感兴趣的:(C语言,数据结构,python,开发语言)