在 C++ 中检查一个字符串是不是是另一个字符串的排列
Posted
技术标签:
【中文标题】在 C++ 中检查一个字符串是不是是另一个字符串的排列【英文标题】:Checking if one string is a permutation of another in C++在 C++ 中检查一个字符串是否是另一个字符串的排列 【发布时间】:2016-06-07 02:50:51 【问题描述】:我一直在研究一些编程问题,试图用数据结构和算法来刷新我的记忆。问题是检查一个字符串是否是另一个字符串的排列。
我见过的很多代码解决方案都会对每个字符串进行排序,然后检查排序后的字符串是否彼此相等。这通常通过执行以下操作来完成:
sort(strOne.begin(), strOne.end());
sort(strTwo.begin(), strTwo.end());
for (int i = 0; i < strOne.length(); i++)
if (strOne[i] != strTwo[i])
return false;
但是,我想知道在对字符串进行排序后,您是否可以直接比较字符串而不是使用 for 循环。例如,
if (strOne == strTwo)
return true;
我是否遗漏了第二个选项不起作用的东西?我觉得我错过了一个基本概念,因为似乎大多数解决方案都有 for 循环来迭代字符串。
提前致谢!
【问题讨论】:
std::is_permutation
。就用它吧。或者如果你想知道它是如何工作的,你可以阅读它的代码。
link 示例......
***.com/questions/36818877/…
【参考方案1】:
您可以使用 str1.compare(str2) 按字典顺序比较字符串,如果相等则返回 0。
但是,您的解决方案需要 O(nlogn) 复杂度,并且可以在线性时间内解决...
【讨论】:
推荐str1.compare(str2) != 0
超过str1 == str2
没有合理的理由;我只从缺乏运算符重载的语言的程序员那里看到过这样的建议。不过关于线性时间的要点:只需迭代第一个字符串 ++freq[s[i]]
,其中 freq
可以按字符值索引并默认为 0,然后是第二个字符串 --freq[s[i]]
,然后检查没有非零值。
(多想一想——假设你在前面return false
字符串长度不同,你可以使用if (--freq[s[i]] < 0) return false;
提前纾困,然后就不需要决赛了在return true
之前检查非零)。
如果str1.compare(str2)
有效,那么std::set_symmetric_difference
也应该有效pastebin.com/2i3quAQJ【参考方案2】:
请在所有可能的条件下明确返回真或假。否则你可能得不到想要的结果。
在第一个代码块中,您没有在 for 循环之外定义返回值。 因此,明确地说,如果两个字符串相等,您的函数将不返回任何内容。
在第二个代码块中,您没有在 if 语句之外定义返回值。 因此,明确地,如果两个字符串不相等,您的函数将不返回任何内容。
【讨论】:
【参考方案3】:std::sort( strOne.begin(), strOne.end() );
std::sort( strTwo.begin(), strTwo.end() );
return strOne == strTwo;
足够了。
我的建议是使用std::unordered_map
即
std::unordered_map< char, unsigned > umapOne;
std::unordered_map< char, unsigned > umapTwo;
for( char c : strOne ) ++umapOne[c];
for( char c : strTwo ) ++umapTwo[c];
return umapOne == umapTwo;
作为一种优化,您可以在解决方案的顶部添加
if( strOne.size() != strTwo.size() ) return false;
更好的std::unordered_map
解决方案,
if( strOne.size() != strTwo.size() ) return false; // required
std::unordered_map< char, int > umap;
for( char c : strOne ) ++umap[c];
for( char c : strTwo ) if( --umap[c] < 0 ) return false;
return true;
如果你只需要解决一个问题而不知道怎么做,你可以使用std::is_permutation
return std::is_permutation( strOne.begin(), strOne.end(), strTwo.begin(), strTwo.end() );
【讨论】:
【参考方案4】:只是为了补充其他答案,如果您先验地知道两个字符串的字符范围('a' - 'z')或类似的东西,那么您可以在线性时间内解决问题。这个问题在 O(n log n) 内解决可能没问题,但情况并非总是如此。
这将是我解决此问题的版本。它使用的事实是,如果两个词对每个字符的频率相等,则可以将一个词重新排列到另一个词中。
#include <string>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
int main()
string a, b;
cin >> a >> b;
vector<int> frequencyOfLettersA(26, 0);
vector<int> frequencyOfLettersB(26, 0);
for(char c : a)
frequencyOfLettersA[c - 'a']++;
for(char c : b)
frequencyOfLettersB[c - 'a']++;
bool isPermutation = true;
for(int i = 0; i < 26; ++i)
if(frequencyOfLettersA[i] != frequencyOfLettersB[i])
isPermutation = false;
break;
if(isPermutation)
cout << "Yes" << endl;
else
cout << "No" << endl;
【讨论】:
【参考方案5】:STL方式是:
std::string str0, str1;
bool IsPermutation = std::is_permutation(str0.begin(), str0.end(), str1.begin(), str1.end());
【讨论】:
【参考方案6】:是的,你可以直接比较字符串。在函数中使用字符串比较的正确方法是
return str1 == str2;
环岛路
if (str1 == str2)
return true;
else
return false;
有主要缺点:它要长几倍,很容易忘记else
部分(您刚刚做过),并且在重构期间更容易中断。
【讨论】:
以上是关于在 C++ 中检查一个字符串是不是是另一个字符串的排列的主要内容,如果未能解决你的问题,请参考以下文章
如何检查一个字符串“StartsWith”是不是是另一个字符串?