[英]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.