簡體   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