[英]Anagram of 2 string : I don't understand what is the problem with my code
我有我的代码,它返回制作字谜所需的最小 integer 删除:
#include <bits/stdc++.h>
using namespace std;
int makeAnagram(string a, string b) {
int count = 0;
for(auto it=a.begin(); it!=a.end(); it++){
if(find(b.begin(), b.end(), *it) == b.end()){
a.erase(it);
count++;
}
}
for(auto it = b.begin(); it != b.end(); it++){
if(find(a.begin(), a.end(), *it) == a.end()){
b.erase(it);
count++;
}
}
return count;
}
而且它根本不起作用,我不明白为什么,主要测试是:
int main()
{
string a={'a','b','c'};
string b={'c','d','e'};
int res = makeAnagram(a, b);
cout << res << "\n";
return 0;
}
控制台应该返回 4,但它返回 2,并且字符串 a 和 b 在程序末尾有 2 个元素,而它们应该是 1 大小
您的方法的问题是您在迭代期间删除了元素,但您没有考虑迭代器中的更改,即您应该首先增加迭代器然后删除前一个元素,这是简单的方法
int makeAnagram(string a, string b) {
int A = a.size();
int B = b.size();
int count = 0;
if (A > B)
{
for (auto i = b.begin(); i != b.end(); i++)
{
size_t t = a.find(*i);
if (t == std::string::npos)
{
count++;
}
else
{
a.erase(a.begin() + t);
}
}
count = count + A - (b.size() - count);
}
else
{for (auto i = a.begin(); i != a.end(); i++)
{
size_t t = b.find(*i);
if (t == std::string::npos)
{
count++;
}
else
{
b.erase(b.begin() + t);
}
}
count = count + B - (a.size() - count);
}
return count;
}
嗯,我以为我已经在其他地方回答了这个问题。 但不管怎么说。 让我们再试一次。 重要的是算法。 我几乎怀疑下面是否有比我更快的答案。 但是,我们永远不知道。 . .
而且,一如既往,最重要的是找到一个好的算法。 然后,我们也许可以做一些好的编码来获得一个快速的解决方案。 但最重要的是算法。
让我们开始思考它。 让我们从 2 个简单的字符串开始
abbccc
abbccc
它们是相同的,所以没有什么可以删除的。 结果是0。但是我们怎么能得出这个结论呢? 我们可以考虑对字符进行排序、搜索、比较,但正确的方法是计算字符的出现次数。 在谈论 Anagrams 时,几乎每次都会这样做。 所以,这里我们有每个字符串 1 a、2 b、3c。
如果我们比较字符串中每个字符的计数,那么它们是相同的。
如果我们记得很久以前的学生时代或 C 代码,甚至更好的 Micro Controller 汇编代码,那么我们就知道可以通过减法进行比较。 例子。 让我们看一些例子:6-4=2 或 3-4= -1 或 7-7=0。 因此,可以使用该方法。
2 个字符串的下一个示例:
bbcccddd
abbccc
我们已经看到,我们需要从第一个字符串中删除 3*"d" 并从第二个字符串中删除一个 "a"。 共删除 4 条。 让我们看一下计数: String a: b->2, c->3 d->3, String b: a->1, b->2, c->3
而且,现在让我们比较一下,所以减去:a->0-1= -1, b->2-2=0, c->3-3=0, d->3-0=3。
如果我们将增量的绝对值相加,那么我们就有了结果。 3+abs(-1)=4
OK,现在,我们可以开始编写这个算法了。
std::cin
读取 2 个源字符串 a 和 b。 为此,我们将使用std::getline
然后我们就有了结果。
请注意,您只需要 26 个计数器的数组大小,因为要求 state 字符串字符的输入范围为“a”-“z”。 但是,我们需要通过从字符中始终减去“a”来将“a”-“z”的字符值 map 转换为索引 0-25。 但是由于有点浪费空间(230 字节),我们可以省略减法。
请参见:
#include <iostream>
#include <string>
int main() {
// Here we will store the input, 2 strings to check
std::string a{}, b{};
// Read the strings from std::cin
std::getline(std::cin, a);
std::getline(std::cin, b);
// Here we will count the occurence of characters.
//We assume a char type with a width of 8 bit
int counter[256]{};
// Count occurence of characters in string a
// And Count occurence of characters in string b negatively
for (const char c : a) ++counter[c];
for (const char c : b) --counter[c];
// Calculate result
int charactersToDeleteForAnagram{};
for (int c : counter) charactersToDeleteForAnagram += std::abs(c);
std::cout << charactersToDeleteForAnagram << '\n';
return 0;
}
我们还可以转换为 C++,我们使用输入检查、用于计数的std::unordered_map
和用于求和的std::accumulate
。 char 类型的内部表示也无关紧要。 而且原理是一样的。
我不知道,如果这慢得多。 . .
请参见:
#include <iostream>
#include <string>
#include <unordered_map>
#include <numeric>
int main() {
// Here we will store the input, 2 strings to check
std::string aString{}, bString{};
// Read the strings from std::cin
if (std::getline(std::cin, aString) && std::getline(std::cin, bString)) {
// Here we will count the occurence of characters.
//We assume a char type with a width of 8 bit
std::unordered_map<char, int> counter{};
// Count occurence of characters in string a
// And Count occurence of characters in string b negatively
for (const char character : aString) counter[character]++;
for (const char character : bString) counter[character]--;
// Calculate result and show to user
std::cout << std::accumulate(counter.begin(), counter.end(), 0U,
[](size_t sum, const auto& counter) { return sum + std::abs(counter.second); }) << '\n';
}
else std::cerr << "\nError: Problem with input\n";
return 0;
}
如果您有任何问题,请询问。
语言:C++ 17
使用 MS Visual Studio 2019 社区版编译和测试
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.