LeetCode整理--删除排序数组中的重复项

题目要求

在这里插入图片描述
第一种解题思路

因为数组是已经排好序的有序数组,所以后面的元素一定是大于等于前面的数字的,所以我们只需要判断后一个数字是否与前一个数字相等,如果相等就让后一个继续向后,直到不等于当前数为止,如果不相等就让前面的下标向后移动一位赋值,最后的长度就是前面下标+1

// 前面的解释有点难以理解,看代码很容易理解
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() == 0)
        {
            return 0;
        }
        int index = 0;
        for(int i = 1; i < nums.size(); i++)
        {
            if(nums[index] != nums[i])
            {
                nums[++index] = nums[i];
            }
        }
        return index + 1;
    }
};

第二种解决思路

利用STL中的distance以及unique接口:
distance有两个参数为迭代器,计算两个迭代器之间的距离;

distance的介绍

unique的两个参数也为迭代器,它保证了相邻的数据之间没有重复项,例如:{ 1, 2, 2, 3, 3, 3, 2, 4, 4}的结果就是{1, 2, 3, 2, 4};可以发现其中仍然是存在重复项的,因为unique只保证相邻的两个数据是唯一的,在本题中不会出现这个问题,因为题中的数组为有序的。返回值也是一个迭代器,表示相邻的不重复项的最后一个地址。

unique的介绍

// 代码实现简单,但是需要对接口熟悉
// 接口在头文件 #include <algorithm>中
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
       return distance(nums.begin(), unique(nums.begin(), nums.end()));
    }
};

第三中解决思路

同样用到了STL中的接口upper_bound
upper_bound需要在排序数组中使用
在从小到大的数组中,upper_bound的作用是利用二分查找,找到第一个大于val的值,直到找到 last位置

upper_bound介绍

// 头文件#include <algorithm>
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
       return removeDuplicates(nums.begin(), nums.end(), nums.begin()) - nums.begin();
    }
    template<class InIt, class OutIt>
    OutIt removeDuplicates(InIt first, InIt last, OutIt output)
    {
        while(first != last)
        {
            *output++ = *first;
            first = upper_bound(first, last, *first);
        }
        return output;
    }
    
};

扩展
在这里插入图片描述
第一种解题思路

与第一题的解题方式类似
从第三个元素开始,与第一个元素相比较,相同则第一个元素的出现次数一定是大于3个的,不相同就比较下一个与第二个元素是否相同,以此类推

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() < 2)
        {
            return nums.size();
        }
        int index = 2;
        for(int i = 2; i < nums.size(); ++i)
        {
            if(nums[i] != nums[index - 2])
            {
                nums[index++] = nums[i];
            }
        }
        return index;
    }
};

最终返回index的原因是index的位置在有效数据的下一个位置,而下标是从0开始的,所以index就表示长度

第二种思路

判断一个元素的左右两边是否相同,相同表示当前元素已经超过两个,这时候继续向后走,直到走到左右两边不相同或走到最后一个元素的前一个。

为什么走到最后一个前一个元素就可以直接赋值了?
因为赋值的永远是相同元素中的第一个和最后一个,到了倒数第二个元素时,左右两边还是相同就可以直接将最后一个元素赋值了。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {  
        int index = 0;
        for(int i = 0; i < nums.size(); ++i)
        {
            if(i > 0 && i < nums.size() - 1 
            		 && nums[i - 1] == nums[i] 
            		 && nums[i] == nums[i + 1])
                continue;
            nums[index++] = nums[i];
        }
        return index;
    }
};

第二种方法相较于第一种方法更为简洁;但是第一种方法的扩展性较好,将出现2的位置改位3即可解答最多出现三次的问题。
如果是无序数组,则需要使用hashmap来记录数字出现次数

解题思路来自《LeetCode题解》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值