LeetCode # 316 Remove-Duplicate Letters array of strings

Description  


 

Given a string which contains only lowercase letters, remove duplicate letters so that every letter appears once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.

Example 1:

Input: "bcabc"
Output: "abc"
Example 2:

Input: "cbacdcbc"
Output: "acdb"

 

 

Thinking


 

  Elderly recycled to re-create the first four days.

 

  This question is quite difficult, they want to, not thought out, looked tubing with a video explaining the idea after knocking out the video link below:

  " LeetCode 316. The interpretation of the Remove Duplicate Letters Chinese Version Chinese "

 

  One of the difficulties of this problem is how to understand questions correctly, my idea is this:

  Input: a string containing only lowercase

  Output: lexicographically smallest string, each letter appears only once, but only if there is a letter that appears in the input string once, then it can not change the position of the output string, and the position of the element can appear more than once each Alternatively,

 

  Input string such as "becabd c", b appears twice, so that in the output string, b may be the first letter may also occur after the "e, c, a" three letters; however, because the input string only e and e in a second position, regardless of how to sort, the first output string must be a letter or e as the second letter of the letter string.

 

  Once you understand the topic, start problem solving.

  Traversing input string, using a statistical number of occurrences of each letter map, the time complexity is O (n).

  After again traversing the input string, using a string end result object result is stored, the current scan characters required and the final character result is circulated, and if lexicographical currently scanned character is smaller, and result in subsequent scans last character will appear in (described position may be replaced, as in the above example B), put the end result character pop out.

  At the same time, also we need to add an access array, mark whether a character has been accessed prevent BUG same characters repeated addition result of.

 

  It is worth noting that before the C ++ 11, string and not a very good function with a time constant of deleting the last character, C ++ there came pop_back constant time after 11 ().

  It is strange, vector <char> additions and deletions operation sometimes seems to be higher than the efficiency of the string a lot, the way to achieve 4ms, but steady string 8ms, but the bottom string is a vector <char> to achieve, and this little metaphysics, and then after a wave of serious study.

 

  After AC, find efficiencies and map unordered_map actually a lot of difference (ranking 40% and 10% difference), somewhat taken aback, access to information was later discovered that two containers scenarios are as follows:

map-based red-black tree, keeping stable the query efficiency is O (logN) 
unordered_map based on Hash, the best query efficiency is O ( 1 ) 

10W, 100W magnitude time-consuming, can be found, additions and deletions on the map in the investigation were three weak in unordered_map, and memory usage, then map a little less, but not obvious 

⭐️ Conclusion: (keyword) or ordering of the need for a single query time-critical application scenarios, use a map, you should use the remaining cases unordered_map

 

 

  AC code is as follows:

  vector version

class Solution {
public:
    string removeDuplicateLetters(string s) {
        if (s.size() == 0) return s;
        
        // map from letter to numbers appeared in remaining string
        unordered_map<char, int> remain_cnt;
        // map from letter to whether the letter is used
        unordered_map<char, bool> is_used;
        
        for (auto letter : s) {
            auto it = remain_cnt.find(letter);
            if (it == remain_cnt.end()) {
                remain_cnt[letter] = 1;
                is_used[letter] = false;
            } else {
                it->second = it->second + 1;
            }
        }
        
        vector<char> result;
        for (auto letter : s) {
            auto remain_cnt_it = remain_cnt.find(letter);
            auto letter_used_it = is_used.find(letter);
            
            if (result.empty()) {
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                letter_used_it->second = true;
                continue;
            }

            if (letter_used_it->second) {
                remain_cnt_it->second = remain_cnt_it->second - 1;
                continue;
            }
            
            auto last_letter = result.back();
            if (remain_cnt[last_letter] != 0 
                    && last_letter > letter) {
                while (remain_cnt[last_letter] != 0 &&
                        last_letter > letter) {
                    result.pop_back();
                    is_used[last_letter] = false;
                    if (!result.empty()) {
                        last_letter = result.back();
                    } else {
                        break;
                    }
                }
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                is_used[letter] = true;
            } else {
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                is_used[letter] = true;
            }
        }
        
        return string(result.cbegin(), result.cend());
    }
};

 

  string version (in fact, and vector interface is the same, and there is no difference on grammar)

class Solution {
public:
    string removeDuplicateLetters(string s) {
        if (s.size() == 0) return s;
        
        // map from letter to numbers appeared in remaining string
        unordered_map<char, int> remain_cnt;
        // map from letter to whether the letter is used
        unordered_map<char, bool> is_used;
        
        for (auto letter : s) {
            auto it = remain_cnt.find(letter);
            if (it == remain_cnt.end()) {
                remain_cnt[letter] = 1;
                is_used[letter] = false;
            } else {
                it->second = it->second + 1;
            }
        }
        
        string result;
        for (auto letter : s) {
            auto remain_cnt_it = remain_cnt.find(letter);
            auto letter_used_it = is_used.find(letter);
            
            if (result.empty()) {
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                letter_used_it->second = true;
                continue;
            }

            if (letter_used_it->second) {
                remain_cnt_it->second = remain_cnt_it->second - 1;
                continue;
            }
            
            auto last_letter = result.back();
            if (remain_cnt[last_letter] != 0 
                    && last_letter > letter) {
                while (remain_cnt[last_letter] != 0 &&
                        last_letter > letter) {
                    result.pop_back();
                    is_used[last_letter] = false;
                    if (!result.empty()) {
                        last_letter = result.back();
                    } else {
                        break;
                    }
                }
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                is_used[letter] = true;
            } else {
                result.push_back(letter);
                remain_cnt_it->second = remain_cnt_it->second - 1;
                is_used[letter] = true;
            }
        }
        
        return result;
    }
};

 

Guess you like

Origin www.cnblogs.com/Bw98blogs/p/12633712.html