有没有更好(更有效)的方法来确定一个字符串是否可以由另一个字符串的字符组成

Is there a better (more efficient) way to find if a string can be formed from chars of another string?

本文关键字:字符串 是否 另一个 字符 一个 有效 更好 方法 有没有      更新时间:2023-10-16

这很有趣,因为这可能是一个面试问题,所以最好知道解决这个问题的最有效算法。我提出了一个解决方案(包含其他人的解决方案的元素),它需要map<char, int>来存储第一个字符串中的字母作为键,并将它们出现的数字作为值。然后,该算法查找container字符串中的每个字母,并检查映射中是否已经有条目。如果是,则递减其值,直到它为零,依此类推;直到container结束(失败)或者直到map为空(成功)。

该算法的复杂度为O(n),O(n)是最坏情况(失败)。

你知道更好的方法吗?

以下是我编写、测试和评论的代码:

// takes a word we need to find, and the container that might the letters for it
bool stringExists(string word, string container) {
    // success is initially false
    bool success = false;       
    // key = char representing a letter; value = int = number of occurrences within a word
    map<char, int> wordMap;     
    // loop through each letter in the word
    for (unsigned i = 0; i < word.length(); i++) {
        char key = word.at(i); // save this letter as a "key" in a char
        if (wordMap.find(key) == wordMap.end())     // if letter doesn't exist in the map...
            wordMap.insert(make_pair(key, 1));      // add it to the map with initial value of 1
        else
            wordMap.at(key)++;                      // otherwise, increment its value
    }
    for (int i = 0; i < container.size() && !success; i++) {
        char key = container.at(i);
        // if found
        if (wordMap.find(key) != wordMap.end()) {
            if (wordMap.at(key) == 1) { // if this is the last occurrence of this key in map 
                wordMap.erase(key);     // remove this pair
                if (wordMap.empty())    // all the letters were found in the container!
                    success = true;     // this will stop the for loop from running
            }
            else                        // else, if there are more values of this key
                wordMap.at(key)--;      // decrement the count
        }
    }
    return success;
}

不要使用std::map。通常它具有O(log N)写入和O(log N)访问。和malloc呼吁写。

对于char,您可以使用简单的int freq[256]表(如果您愿意,也可以使用std::vector)。

bool stringExists(const string& word, const string& cont) {
  int freq[CHAR_MAX-CHAR_MIN+1]={0};
  for (int c: cont) ++freq[c-CHAR_MIN];
  for (int c: word) if(--freq[c-CHAR_MIN]<0)  return false;
  return true;
}

该代码的复杂度为O(N + M),其中NM分别为:word.size()cont.size()。我想,即使是小规模的输入,它也至少快100倍。