C++ 的多种去重方法

# vector 利用 set

第一种方法是简单的利用 set 的特性,这部分代码比较简单

代码如下:

#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main() {
    int myints[] = {1, 2, 3, 1, 1};
    int len = sizeof(myints) / sizeof(int);
    vector<int> vec(myints, myints + len);
    //将普通数组转换为 vector
    set<int> s(vec.begin(), vec.end());
    //将 vector 转换为 set,set 数据结构自动去重
    vec.assign(s.begin(), s.end());
    //再将 set 转换为 vector 进行使用
    for (auto &x : vec) cout << x << " ";
    return 0;
}

# 结合 sort 和 unique 函数

unique() 函数将相邻且重复的元素删除,然后空出的位置用他后面的元素一次向前移动覆盖
然后返回边界元素的迭代器,供 erase 等类似函数调用
再用 erase 函数隐藏掉从这个元素到最后元素的所有的元素。(只改变 size 不改变 capacity

所以想要去重的话,可以先进行排序,这样重复元素就会堆一起了,调用 unique() 函数,再调用 erase 函数隐藏重复元素。

代码如下:

#include <algorithm>  // algorithm 库包含了 sort 和 unique 函数
#include <iostream>
#include <vector>
using namespace std;
int main() {
    int myints[] = {1, 2, 3, 1, 1};
    int len = sizeof(myints) / sizeof(int);
    vector<int> vec(myints, myints + len);
    // 将已有的数组转换为 vector 方便调用各种函数接口
    sort(vec.begin(), vec.end());
    // 对 vector 进行排序 1 1 1 2 3
    auto ret = unique(vec.begin(), vec.end());
    // 将 vector 进行去重的操作,将所有元素的个数限制到最大一个,
    // 后面的元素依次向前移动, 后面元素移动之前的位置对应的值,仍然不变
    // 1 2 3 2 3
    // 同 后面的 remove 函数,ret 指向的是相关的边界,可以供 erase 函数使用
    // 排列完成后调用 earse 和 unique 接口,两个函数的参数都是 begin 和 end
    vec.erase(ret, vec.end());
    // vec.erase(unique(vec.begin(), vec.end()), vec.end());
    for (auto &i : vec) cout << i << " ";
    // 1 2 3
    for (int i = 0; i < vec.capacity(); i++) cout << vec[i] << " ";
    // 1 2 3 2 3
    return 0;
}

# C++ 自带的 remove 函数:

同 unique 函数的返回值
目的是删除 vector 中等于目标值的所有元素

代码如下:

#include <algorithm> // algorithm 函数包含了 remove 函数
#include <iostream>
#include <vector>
using namespace std;
int main() {
    std::vector<int> vec(0);
    for (int i = 0; i < 10; i++) {
        vec.push_back(i + 1);
    }
    vec[1] = 7, vec[0] = 7, vec[2] = 7;
    vec.push_back(-1);
    // vector: 7 7 7 4 5 6 7 8 9 10 -1
    auto ret = std::remove(vec.begin(), vec.end(), 7);
    cout << *ret << endl;
    // *ret == 8 
    // vector: 4 5 6 8 9 10 -1 8 9 10 -1
    // 可见 remove 的作用就是将所有等于目标值的函数删除,
    // 然后后面的元素一次向前移动,
    // 但是向前移动之后,之前在后面的元素的值仍然不变
    vec.erase(ret, vec.end());
    // 4 5 6 8 9 10 -1
    // 使用 remove 函数获取删除目标值之后的边界下标
    // 然后使用 erase 函数将边界之后的元素进行 空间隐藏
    for (auto &i : vec) {
        std::cout << i << " ";
    }
    // 4 5 6 8 9 10 -1
    for (int i = 0; i < 10; i++) {
        cout << vec[i] << " ";
    }
    // 4 5 6 8 9 10 -1 8 9 10 
    // (仍然存在其余元素, erase 只做了空间隐藏)
    // erase 将 vector 的 size 进行相应的缩小, 但是 capacity 仍然不变
    return 0;
}

# 双指针手写 unique

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/

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