繁体   English   中英

2 个字符串的字谜:我不明白我的代码有什么问题

[英]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,现在,我们可以开始编写这个算法了。

  1. std::cin读取 2 个源字符串 a 和 b。 为此,我们将使用std::getline
  2. 接下来我们将“计数器”定义为一个数组。 我们假设一个 char 是 8 位宽,最大字符数是 256
  3. 我们积极计算第一个字符串的所有字符出现
  4. 现在我们一步一步进行比较和计数,通过减少第二个字符串中每个字符出现的计数器
  5. 然后我们累积所有计数器(对于所有出现的字符)。 我们使用绝对值,因为数字可能是负数。

然后我们就有了结果。

请注意,您只需要 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM