我一直在练习编程问题并遇到过这个问题
给定字符串A和B,检查字符串B是否为字符串A的排列
我写了我的答案并将其与书籍答案进行了比较,但我的答案完全不同。然后我研究了StackOverflow并且没有看到有人用我的解决方案回答这个问题。
我见过两种解决方案
对两个字符串进行排序,然后对它们进行比较。这需要O(nlogn)时间,并且根据排序算法,它将占用O(n),O(logn)或O(1)内存。
创建一个哈希映射,并使键成为字符串的字符,并将值初始化为0.当您在字符串A中看到一个字符时,将值递增1.当您看到一个字符时字符串B将其递减1.最后,如果是置换,则所有值都应为0。这需要O(n)时间和O(n)内存。
我的解决方案是散列字符串,然后比较散列值,如果它们相等,则字符串必须是排列。
我在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)内存中运行。
问题
修改
正如大家都指出的那样,我的解决方案无法使用。由于ad
将哈希到bc
,而这些不是排列。
答案 0 :(得分:1)
7
,因此您的哈希检查字符串是否总和为相同值,而不是它们是每个字符串的排列其他hash = sum(c[i] * alpha ^ (i - 1))
,其中c
是您的字符串,alpha
是字母表中的字母数;但是,由于哈希现在是唯一的,hash(a) == hash(b)
暗示a == b
这不是你想要的; (这也有自己的其他问题,如溢出,非常复杂的计算)我会坚持使用选项1:使用固定字母大小a
,您可以使用O(n)
时间O(a)
空间计数排序,例如显然是最佳解决方案对于这个问题(恒定空间,以输入时间为界)。
选项2对我来说似乎也是错误的,但也许我只是不理解它:如果输入是aa
和bb
,翻转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;
}