【问题标题】:Designing hash set in leetcode, code gives run time error在leetcode中设计哈希集,代码给出运行时错误
【发布时间】:2018-07-12 01:41:04
【问题描述】:

我正在尝试解决有关设计 HashSet 的问题。

在不使用任何内置哈希表库的情况下设计一个 HashSet。

具体来说,你的设计应该包括这两个功能:

add(value):向 HashSet 中插入一个值。
contains(value) : 返回该值是否存在于 HashSet 中。

remove(value):删除 HashSet 中的一个值。如果 HashSet 中不存在该值,请执行 什么都没有。

例子:

MyHashSet hashSet = new MyHashSet(); hashSet.add(1);
hashSet.add(2); hashSet.contains(1); // 返回真 hashSet.contains(3); // 返回 false(未找到) hashSet.add(2);
hashSet.contains(2); // 返回真 hashSet.remove(2);
hashSet.contains(2); // 返回 false(已删除)

注意:

所有值都将在 [1, 1000000] 的范围内。的数量 操作将在 [1, 10000] 的范围内。请不要使用 内置 HashSet 库。

以下代码在本地运行良好,但提交失败,出现错误,

运行时错误消息: 对“int”类型的未对齐地址 0x736c61662c657572 的引用绑定,这需要 4 字节对齐

最后执行的输入: ["MyHashSet","add","re​​move","add","contains","add","re​​move","add","add","add","add"] [[],[6],[4],[17],[14],[14],[17],[14],[14],[18],[14]]

class MyHashSet { public:
vector<vector<int>> setHash;
MyHashSet() {
    setHash.reserve(10000);
}

void add(int key) {
    int bucket = key % 10000;
    vector<int>::iterator it;
    it = find(setHash[bucket].begin(),setHash[bucket].end(),key);
    if(it == setHash[bucket].end()){
        setHash[bucket].push_back(key);
    }
}

void remove(int key) {
    int bucket = key % 10000;
    vector<int>::iterator it1;
    it1 = find(setHash[bucket].begin(),setHash[bucket].end(),key);
    if(it1 != setHash[bucket].end()){
        int index = distance(it1,setHash[bucket].begin());
        setHash[bucket].erase(setHash[bucket].begin()+index);
    }

}

/** Returns true if this set did not already contain the specified element */
bool contains(int key) {
    int bucket = key % 10000;
    vector<int>::iterator it2;
    it2 = find(setHash[bucket].begin(),setHash[bucket].end(),key);
        if(it2 != setHash[bucket].end()){
            return true;
        }

    return false;
}

};

我怀疑是因为内存问题。但由于我仍在学习 c++ 的基础知识,所以无法弄清楚。

【问题讨论】:

  • 法官似乎很友善并提供了破坏性输入。您应该给自己写一个简单的main 来执行这些输入,然后看看会发生什么。如果您已经这样做了,请将其添加到问题中。
  • int index = distance(it1,setHash[bucket].begin()); 这看起来很奇怪。你不应该替换distance中的参数吗?
  • 方便阅读std::vector::reservestd::vector::resize。阅读后,问问自己,“我用对了吗?”
  • 以下代码在本地运行良好 -- 将您的setHash[bucket] 替换为setHash.at(bucket),您将看到它不再在本地运行良好。事实上,std::out_of_range 抛出的异常会告诉你问题所在。
  • “不可能重新分配的向量” 不完全是。它所做的是在不构造元素和更新元素计数的情况下预分配存储。然后,您可以使用 push 和 emplace 功能而无需调整大小,直到超出预留容量。它可以重新分配。您的程序失败,因为已分配 setHash[bucket] 但未包含正确构造的 vector&lt;int&gt;setHash[bucket].push_back(key); 会将 int 写入内存中未适当对齐以处理 int 的某个随机位置

标签: c++ runtime-error


【解决方案1】:

如果您的问题是如何修复您的实施,我会听取 cmets 中的建议。

如果您想了解 C++ 并以最佳方式解决问题,我会使用 std::bitset。他们给你定义的输入范围 [1,1000000] 的事实让我相信他们正在寻找这样的东西。

这可能属于内置哈希表库的范畴,所以here is a potential implementation

class MyHashSet {
public:
    void add(int key) {
        flags.set(key);
    }
    void remove(int key) {
        flags.reset(key);
    }
    bool contains(int key) const {
        return flags[key];
    }
private:
    bitset<1000000+1> flags;
};

在我的平台上,这需要大约 16kB(而 10000 个向量需要 30kB+)。它也不需要动态内存分配。

如果您认为这是题外话或作弊,请提供 LeetCode 问题的标题/编号,以便我可以使用他们的测试用例处理您的代码草稿。我现在也在研究哈希表,所以这是双赢的。

【讨论】:

    猜你喜欢
    • 2017-03-30
    • 2017-05-16
    • 2011-05-23
    • 2016-11-04
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    相关资源
    最近更新 更多