问题
This is interesting because it's a possible interview question, so it would be good to know the most efficient algorithm for this problem. I came up with a solution (which contains elements of other people's solutions) that requires a map<char, int>
to store letters from the first string as keys, and numbers of their occurrences as values. The algorithm then looks through each letter in the container
string and checks if there's already an entry in the map. If so, decrement its value until it's zero and so on; until the container
is finished (failure), or until the map
is empty (success).
The complexity of this algorithm is O(n), O(n) being the worst-case scenario (failure).
Do you know a better way?
Here is the code that I've written, tested and commented:
// 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;
}
回答1:
Do not use std::map
. Usually it has O(log N)
write, and O(log N)
access. And malloc call on write.
For char
you can use simple int freq[256]
table (or std::vector
if you are so inclined).
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;
}
Complexity of this code is O(N + M)
, where N
and M
are: word.size()
and cont.size()
. And I would guess that it is at least 100 times faster even from small sized inputs.
来源:https://stackoverflow.com/questions/17991135/is-there-a-better-more-efficient-way-to-find-if-a-string-can-be-formed-from-ch