【问题标题】:Check if a string contains duplicates using std::map使用 std::map 检查字符串是否包含重复项
【发布时间】:2017-03-07 06:04:34
【问题描述】:

我有一个函数,通过将每个字符作为键来使用 std::map 检查字符串是否包含重复项。无法弄清楚为什么这不起作用。

#include<iostream>
#include<map>
#include<string>
int unique_char(std::string s){
 for(int i=0 ; i < s.size(); i++ )
  {
    std::map<char,int> uniq_hash_table;
    std::pair<std::map<char,int>::iterator,bool> ret;
    ret = uniq_hash_table.insert(std::pair<char,int>(s[i],0));
    if(ret.second==false)
     {
      std::cout << "The string contains duplicates" << std::endl;
      return 1;
     }
  }
return 0;
}
int main()
{
 std::string s="abcd";
 std::string s1="aabc";
 if(unique_char(s)==0){
 std::cout << "The 1st string does not contain duplicates" << std::endl;}
 if(unique_char(s1)==0){
 std::cout << "The 2nd string does not contain duplicates" << std::endl;}
 return 0;
}

程序为这两个示例返回“字符串不包含重复项”。

ps:我故意使用 std::map 来获得 O(n) 解决方案。

【问题讨论】:

  • "uniq_hash_table" 是一个极具误导性的名称...
  • 当您似乎只需要一组地图时,为什么还要使用地图?
  • 遗憾的是,我相信这是任务。今天下午我们有另一个提问者完成了类似的任务。不过,另一个提问者必须实现哈希表。

标签: c++ string dictionary


【解决方案1】:

您的解决方案不起作用,因为您的 std::map&lt;char,int&gt; 在循环的每次迭代中都会重新创建。然后,在循环的每次迭代中,地图都是空的。那么,就没有重复了。

最好使用std::set&lt;char&gt;。你可以这样做:

bool contains_duplicated_char(const std::string& s)
{
  std::set<char> check_uniq;
  for(unsigned long int i = 0; i < s.length(); ++i)
    if(!check_uniq.insert(s[i]).second)
      return true; // Duplicated char found
  return false; // No duplicated char found
}

然后这样调用:

const std::string str = "abcdefghijklamnopb";
const bool dupl = contains_duplicated(str);

为了让你的代码更通用(管理更多的数据类型),你也可以这样创建你的函数:

template <typename Type, typename IteratorType>
bool contains_duplicated(IteratorType begin, IteratorType end)
{
  std::set<Type> check_uniq;
  for(IteratorType it = begin; it != end; ++it)
    if(!check_uniq.insert(*it).second)
      return true;
  return false;
}

然后这样称呼它:

std::vector<std::string> vec_str;
vec_str.push_back("Foo");
vec_str.push_back("Bar");
vec_str.push_back("Baz");
vec_str.push_back("Bar");
const bool dupl = contains_duplaicated<std::string>(vec_str.begin(), vec_str.end());
//...
const std::string str = "abcdefab";
const bool dupl2 = contains_duplacated<char>(str.begin(), str.end());
//...
const std::deque<long int> x(4, 0);
x[0] = 1;
x[1] = 17;
x[2] = 31;
x[3] = 0;
const bool dupl3 = contains_duplicated<long int>(x.begin(), x.end());

【讨论】:

    【解决方案2】:

    它不起作用,因为 uniq_hash_tablefor 循环内的每个符号重新创建。

    尝试将它移到函数的开头,就在 for 循环之前:

    std::map<char,int> uniq_hash_table;
    
    for(int i=0 ; i < s.size(); i++ )
    {
        // ...
    }
    

    【讨论】:

    • 确实如此。谢谢。
    【解决方案3】:

    由于您的地图定义位于 for 循环的主体中,因此您在每次迭代时重新创建一个空地图。

    在循环之外声明你的容器,它会更好地工作。

    请注意,如果您从不增加 int 值,则可以使用集合而不是映射。

    【讨论】:

    • 谢谢,这行得通,我是故意使用 std::map 的,因为接下来我会计算重复的数量。
    • @b_mery 好的!我只是想知道你为什么不选择 uniq_hash_table[s[i]]++ 并费心插入一个 0。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 2021-08-17
    • 1970-01-01
    • 2020-09-20
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多