【问题标题】:How to remove all instances of a duplicate from a vector<int> [duplicate]如何从向量中删除所有重复实例<int> [重复]
【发布时间】:2021-05-13 06:24:01
【问题描述】:

我已经尝试解决一个“简单”的 leetcode 问题已经两个小时了,我需要删除多次出现的 int 的每个实例,然后将非重复项添加在一起。我已经尝试了大约 10 种不同的方法,但我只能得到每个 int 的一个副本。这是我写的最好的解决方案,但是给定输入 {1,2,2,3,4} 它会返回 {1,2,3,4} 而预期的输出是 {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)); 

【问题讨论】:

  • unique 只删除非唯一的!因此{2,2} -> {2}
  • 那么我想下一步是想出一个不同的计划,因为你现在的计划行不通。这就是编程游戏和成为程序员的游戏方式。

标签: c++ algorithm vector data-structures stdvector


【解决方案1】:

NlogN 复杂度,您无需预先排序:

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;
    }
}

更新:可以使用std::unordered_multiset,因为我们不需要订购。

【讨论】:

  • 我是整个 Log 计时的新手,但是这个运行得非常快并且效果很好。谢谢你
  • 可以,先回复其他cmet就行了
【解决方案2】:

有很多解决方法,您可以遍历数组并使用map 或其他方式查看该数字存在多少次,然后再次遍历地图并将仅出现一次的数字添加到新数组中。 您可以使用 set 和 map&lt;bool,int&gt;,每次添加新号码时检查它是否存在。

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

【讨论】:

    【解决方案3】:

    您可以使用std::unordered_map&lt;int, bool&gt;,其中第二个(模板)参数(bool)指定值是否重复。它看起来像这样,

    #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;
        }
    }
    

    【讨论】:

    • 您应该将map 重命名为其他名称。此外,OP 想要将这些值相加,而不是将它们复制到向量中。
    【解决方案4】:

    如果 O(n²) 不成问题...

    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);
      });
    

    【讨论】:

    • 很好用的 lambda 函数。在我的 IDE 中工作但不是 leetcode,我认为它不是正确的 C++ 版本
    【解决方案5】:

    set_difference 在这里有很大的帮助。它消除了您描述的方式。

            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";
    
    

    而且……它似乎可以解决问题。

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

    【讨论】:

    • 工作得很好,谢谢。
    【解决方案6】:

    或者您可以在“相等范围”上使用循环,仅累积单个元素长的循环:

            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";
    

    【讨论】:

      猜你喜欢
      • 2014-10-06
      • 1970-01-01
      • 2020-02-02
      • 2019-10-16
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      相关资源
      最近更新 更多