检查字符串是否是另一个字符串

时间:2016-08-12 15:53:46

标签: c++ string algorithm

我一直在练习编程问题并遇到过这个问题

  

给定字符串A和B,检查字符串B是否为字符串A的排列

我写了我的答案并将其与书籍答案进行了比较,但我的答案完全不同。然后我研究了StackOverflow并且没有看到有人用我的解决方案回答这个问题。

我见过两种解决方案

  1. 对两个字符串进行排序,然后对它们进行比较。这需要O(nlogn)时间,并且根据排序算法,它将占用O(n),O(logn)或O(1)内存。

  2. 创建一个哈希映射,并使键成为字符串的字符,并将值初始化为0.当您在字符串A中看到一个字符时,将值递增1.当您看到一个字符时字符串B将其递减1.最后,如果是置换,则所有值都应为0。这需要O(n)时间和O(n)内存。

  3. 我的解决方案是散列字符串,然后比较散列值,如果它们相等,则字符串必须是排列。

    我在C ++中的解决方案

    bool isPerm(string a, string b) {
        if(a.length() != b.length()) return false;
        return hashString(a) == hashString(b);
    }
    
    long hashString(string a) {
        long hashed = 0;
        for(int i = 0; i < a.length(); i++) { 
            hashed += a[i] * 7; // Timed by a prime to make the hash more unique?
        } 
        return hashed;
    }
    

    此解决方案在O(n)时间和O(1)内存中运行。

    问题

    1. 这是一个有效的答案吗?
    2. 如果哈希不够独特,有没有办法让它独一无二?
    3. 修改

      正如大家都指出的那样,我的解决方案无法使用。由于ad将哈希到bc,而这些不是排列。

2 个答案:

答案 0 :(得分:1)

  1. 您提出的哈希值无效,因为多个字符串可以散列到相同的值,这不一定是彼此的排列(例如&#34; 14&#34;和#34; 23&#34;);您实际上只是将字符串的ascii值乘以7,因此您的哈希检查字符串是否总和为相同值,而不是它们是每个字符串的排列其他
  2. 要使散列唯一,您可以将字符串表示为字母表中的数字;即hash = sum(c[i] * alpha ^ (i - 1)),其中c是您的字符串,alpha是字母表中的字母数;但是,由于哈希现在是唯一的,hash(a) == hash(b)暗示a == b这不是你想要的; (这也有自己的其他问题,如溢出,非常复杂的计算)
  3. 我会坚持使用选项1:使用固定字母大小a,您可以使用O(n)时间O(a)空间计数排序,例如显然是最佳解决方案对于这个问题(恒定空间,以输入时间为界)。

    选项2对我来说似乎也是错误的,但也许我只是不理解它:如果输入是aabb,翻转a和{{1两次,一切都是假的,它们看起来不像我的排列。你当然可以为每个字符串保留一个字符出现映射,这对于一个大小为b的字母表需要O(a)内存和O(n)时间,这与计数排序基本相同: )

答案 1 :(得分:1)

一种方法是比较每个字符串的唯一字符数:

#include <unordered_map>
#include <string>

using namespace std;

bool checkPermutation(string a, string b) {
  unordered_map<char, int> aCounts;
  for (auto c : a) {
    aCounts[c]++;
  }

  unordered_map<char, int> bCounts;
  for (auto c : b) {
    bCounts[c]++;
  }

  if (aCounts.size() != bCounts.size()) {
    return false;
  }

  for (auto p : aCounts) {
    char c = p.first;
    if (bCounts.count(c)) {
      if (aCounts.at(c) != bCounts.at(c)) {
        return false;
      }
    } else {
      return false;
    }
  }

  return true;
}