【问题标题】:C++ unordered_map weird behaviourC++ unordered_map 奇怪的行为
【发布时间】:2020-12-23 20:47:39
【问题描述】:

我正在解决 leetcode 问题(总时长可被 60 整除的歌曲对),当我将其更改为 unordered_map 并打印循环内的元素时,下面的解决方案使用了地图;元素的数量远远多于输入

class Solution {
public:
    int numPairsDivisibleBy60(vector<int>& time) {
        map<int, int> mod_d;
        
        for(auto el : time) {
            if(mod_d.count(el % 60) == 0) {
                mod_d[el % 60] = 1;
            }else mod_d[el % 60]++;
        }
        
        int ans = 0, i = 1;
        //cout << "Size: " << mod_d.size() << "\n";
        for(auto el : mod_d) {
            int f = el.first, s = el.second;
            cout << f << " " << 60 - f << "\n";
            ans += mod_d[(60 - f) % 60] * (((60 - f) % 60) == f ? s - 1 : s);
        }
        
        return ans / 2;
    }
};

样本输入测试:[15、63、451、213、37、209、343、319]

输出如下:

3 57
15 45
19 41
29 31
31 29
33 27
37 23
41 19
43 17
45 15
57 3

在循环内打印的元素数量应该只有 8 个,但使用 unordered_map,元素数量要多得多。

不正常的代码如下:

class Solution {
public:
    int numPairsDivisibleBy60(vector<int>& time) {
        unordered_map<int, int> mod_d;
        
        for(auto el : time) {
            if(mod_d.count(el % 60) == 0) {
                mod_d[el % 60] = 1;
            }else mod_d[el % 60]++;
        }
        
        int ans = 0, i = 1;
        //cout << "Size: " << mod_d.size() << "\n";
        for(auto el : mod_d) {
            int f = el.first, s = el.second;
            cout << f << " " << 60 - f << "\n";
            ans += mod_d[(60 - f) % 60] * (((60 - f) % 60) == f ? s - 1 : s);
        }
        
        return ans / 2;
    }
};

唯一的区别是使用unordered_map 而不是map

它错误地将元素打印为:

19 41
43 17
37 23
33 27
31 29
29 31
3 57
41 19
15 45
41 19
3 57
29 31
31 29
57 3
33 27
37 23
43 17
17 43
19 41
23 37
27 33

有人知道为什么会发生这种奇怪的行为吗?

【问题讨论】:

  • 请显示有问题的代码,而不是没有问题的代码 (minimal reproducible example)
  • 还包括输出和预期输出
  • 好的,马上添加
  • 第二个 for 循环在地图中创建了更多元素。根据定义,地图和无序地图以不同的顺序存储它们的内容,碰巧的是,使用 unordered_map 您最终会迭代地图中的新元素,作为同一循环的一部分。使用常规地图则不需要。
  • 在第二个循环中尝试map_d.at(...) 而不是方括号,看看会发生什么

标签: c++


【解决方案1】:

好的,我现在明白了,非常感谢大家的帮助。根据显示访问地图的不同方式的此链接,我看到使用[] 运算符会创建地图中不存在的元素,这是我的错误。 When I should use std::map::at to retrieve map element

修复

首先检查元素是否存在并使用at()访问它

class Solution {
public:
    int numPairsDivisibleBy60(vector<int>& time) {
        unordered_map<int, int> mod_d;

        for(auto el : time) {
            if(mod_d.count(el % 60) == 0) {
                mod_d[el % 60] = 1;
            }else mod_d[el % 60]++;
        }

        int ans = 0, i = 1;
        cout << "Size: " << mod_d.size() << "\n";
        for(auto el : mod_d) {
            int f = el.first, s = el.second;
            cout << f << " " << i++ << "\n";
            if(mod_d.count((60 - f) % 60) > 0) ans += mod_d.at((60 - f) % 60) * (((60 - f) % 60) == f ? s - 1 : s);
        }

        return ans / 2;
    }
};

【讨论】:

  • 请注意,您可以将整个第一个循环简化为:for(auto el : time) { mod_d[el % 60]++; }。由于您的旧代码失败的确切原因,这将起作用:)
  • 是的,这确实是正确的,我一开始也是这样。但是,当它表现得很奇怪时,我认为这可能是一个问题 xD。再次感谢您的建议 :D :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 2018-01-03
  • 2019-04-10
  • 2019-05-24
  • 2016-07-15
  • 2011-06-23
相关资源
最近更新 更多