How to remove all instances of a duplicate from a vector<int> [duplicate]

余生颓废 提交于 2021-02-16 17:57:12

问题


I've been trying to solve an "easy" leetcode question for two hours now where I need to remove every instance of an int that appears more than once then add the non dupes together. I've tried about 10 different ways and I can only get it to go down to one copy of each int. Here is the nicest solution I've written, but given input {1,2,2,3,4} it would return {1,2,3,4} whereas the expected output is {1,3,4}

  sort(nums.begin(), nums.end()); //Sort numerically
  nums.erase(unique(nums.begin(), nums.end()), nums.end()); 
  return (accumulate(nums.begin(), nums.end(), 0)); 

回答1:


This is suboptimal (NlogN complexity), but you avoid needing to pre-sort:

Godbolt

#include <set>
#include <vector>

int main()
{
    std::vector<int> nums = {1,2,2,3,5};

    std::multiset<int> m (nums.begin(), nums.end());

    std::size_t sum = 0;
    for (const auto& elem : m)
    {
      sum += m.count(elem) == 1 ? elem : 0;
    }
}

Update: Could use std::unordered_multiset, as we don't need ordering.




回答2:


There are many workarounds, you can iterate over the array and see how many time the number exists using map or something, and then you iterate again over the map and add the number that only appeared once to a new array. You can use a set and a map<bool,int>, every time you add a new number you check if it exists or not.

if(!map[number]){
set.insert(number);
map[number]=true;
}else{
set.erase(number);
}



回答3:


You can use a std::unordered_map<int, bool> where the second (template) parameter (bool) specifies whether the value is duplicated or not. It'll look something like this,

#include <unordered_map>
...

std::unordered_map<int, bool> uniqueCheckMap;
for (auto i : nums)
{
    if (uniqueCheckMap.find(i) == uniqueCheckMap.end())
        uniqueCheckMap[i] = false;
    else
        uniqueCheckMap[i] = true;    // Set the second (value) as true if duplicate entry is found.
}

nums.clear();
int sum = 0;
for (auto i : uniqueCheckMap)
{
    if (!i.second)
    {
        nums.push_back(i.first);
        sum += i.first;
    }
}



回答4:


If O(n²) is not a problem...

const auto sum=std::accumulate(cbegin(nums), cend(nums), 0,
  [&](const auto &accum, const auto &elem)
  {
    return accum+(std::count(cbegin(nums), cend(nums), elem)>1 ? 0 : elem);
  });



回答5:


set_difference is a great help here. It removes occurences in the way you describe.

        auto ints = vector{4, 3, 2, 2, 1};

        sort(begin(ints), end(ints));
        std::vector<int> unique_ints;
        unique_copy(begin(ints), end(ints), back_inserter(unique_ints));

        vector<int> doubles;
        set_difference( begin(ints), end(ints),
                        begin(unique_ints), end(unique_ints),
                        back_inserter(doubles)
                        );

        vector<int> only_once;
        set_difference( begin(unique_ints), end(unique_ints),
                        begin(doubles), end(doubles),
                        back_inserter(only_once));

        copy(begin(only_once), end(only_once), ostream_iterator<int>(cout, ", "));
        cout << "\n";

Also... it seems to do the trick.

$ g++ -std=c++17 u.cpp  && ./a.out 
1, 3, 4, 



回答6:


Or you could use a loop over 'equal ranges', only accumulating the ones that are a single element long:

        sort(begin(ints), end(ints));

        int acc = 0;
        auto range = equal_range(begin(ints), end(ints), ints.front());

        while(range.first != end(ints)) {
                cout << *range.first << "+ ";
                if (distance(range.first, range.second) == 1){
                        acc += *range.first;
                }
                range = equal_range(range.second, end(ints), *range.second);
        }
        cout << " = " << acc << "\n";


来源:https://stackoverflow.com/questions/66122085/how-to-remove-all-instances-of-a-duplicate-from-a-vectorint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!