LeetCode 451. Sort Characters By Frequency ***** map按值排序转vector,优先队列,频率当下标

来源:互联网 发布:福特汉姆大学 知乎 编辑:程序博客网 时间:2024/06/07 18:37

一、题目

Given a string, sort it in decreasing order based on the frequency of characters.

Example 1:

Input:"tree"Output:"eert"Explanation:'e' appears twice while 'r' and 't' both appear once.So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.

Example 2:

Input:"cccaaa"Output:"cccaaa"Explanation:Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer.Note that "cacaca" is incorrect, as the same characters must be together.

Example 3:

Input:"Aabb"Output:"bbAa"Explanation:"bbaA" is also a valid answer, but "Aabb" is incorrect.Note that 'A' and 'a' are treated as two different characters.
题意:题目很长题意很简单。给定一个字符串,按照字母出现的频率由大到小输出。

注意:后边的举例就是一直在强调的,字符串的题注意事项,字符集的范围,大小写,返回的顺序,空字符。

        该题范围就是大小写字母并且大小写有别,对于出现频率次数相同的串返回顺序任意。

思路:1.统计字符串中各个字母出现的频率存储在map中。

          2.对map按照频率由大到小排序,这里注意是map中按照值排序。

          第一反应是利用stl中提供的sort算法实现,这个想法是好的,不幸的是,sort算法有个限制,利用sort算法只能对序列容器进行排序,就是线性的(如vector,list,deque)。map也是一个集合容器,它里面存储的元素是pair,但是它不是线性存储的(前面提过,像红黑树),所以利用sort不能直接和map结合进行排序。需要将map转为vector。

        参考博客:http://www.cnblogs.com/lakeone/p/5599047.html

          3.对排序后的map取键并相应的频次-1。

class Solution {public:    static bool isless(const pair<char,int> l, const pair<char,int> r)  //静态成员函数???    {    return l.second > r.second;    }    string frequencySort(string s) {        map<char,int> strMap;        for(auto ch:s)        {            strMap[ch]++;        }        vector<pair<char, int>> vecMap(strMap.begin(), strMap.end());  //map按值排序        sort(vecMap.begin(), vecMap.end(), isless);                string outstr;        for (auto temp:vecMap)        {        while (temp.second)        {        outstr += temp.first;   //map取键        temp.second--;        }        }        return outstr;            }};


二、总结。

       使用二元谓词的时候必须得用静态成员函数。关于静态成员函数记录两个博客:

       http://blog.csdn.net/morewindows/article/details/6721430

       http://blog.csdn.net/kerry0071/article/details/25741425/

       至于为啥使用静态成员函数,请查看

       http://blog.csdn.net/xiaxzhou/article/details/71440464

     可以使用lamda表达式也很方便。

    

 sort(vecMap.begin(), vecMap.end(), [](const pair<char, int> l, const pair<char, int> r){return l.second > r.second; }/*isless*/);

三、思路2

思路:一个直观的思路是先统计每个字符的数量,然后将这些字符连同频率放入一个优先队列中,再取出来即可.这种时间复杂度为O(n) + O(m log m),其中n为字符串长度,m为不同字符的个数,在最坏情况下时间复杂度为O(n log n),即所有字符都不一样.

注意优先队列的使用,包含头文件<queue>

string frequencySort(string s) {map<char, int> strMap;for (auto ch : s){strMap[ch]++;}priority_queue<pair<int, char>> priQue;for (auto tempMap:strMap){priQue.push(make_pair(tempMap.second, tempMap.first));}string outstr;while(!priQue.empty()){pair<int, char> temp = priQue.top();outstr.append(temp.first, temp.second);priQue.pop();}return outstr;}


其实我们还有一种可以优化的方法,在统计完字符频率之后利用类似与计数排序的方法,开一个n+1长度大小的数组,将不同的频率字符放到频率的索引处.然后从高到低取得所有字符串.这种方法的好处是在最环情况下依然可以保证时间复杂度为O(n).

string frequencySort(string s) {unordered_map<char, int> freq;vector<string> bucket(s.size() + 1, "");string res;//count frequency of each characterfor (char c : s) freq[c]++;//put character into frequency bucketfor (auto& it : freq) {int n = it.second;char c = it.first;bucket[n].append(n, c);  //bucket中加入n个c}//form descending sorted stringfor (int i = s.size(); i > 0; i--) {if (!bucket[i].empty())res.append(bucket[i]);}return res;}

回顾知识点:最小堆

既然出现从大到小打印,那么就有可能是从小到大打印,除了将map转成vector,调用默认的sort函数排序之外,还有就是优先队列是按照最小堆建立的。

对于内置类型的最大堆,最小堆建立方法:

//默认最大堆的建立 打印输出89,67,36,23,12,4,1        vector<int> num = { 4, 23, 67, 12, 1, 36, 89 };priority_queue<int> test1(num.begin(), num.end());while (!test1.empty()){cout << test1.top() << " ";test1.pop();}cout << endl;       //最小堆的建立包含<functional>,声明方式的改变,输出1,4,12,23,36,67,89       priority_queue<int, vector<int>, greater<int>> test(num.begin(), num.end());while (!test.empty()){cout << test.top()<<" ";test.pop();}

也可使用multiset<int,greater<int>>,按照key由大到小排序

cout << endl;multiset<int, greater<int>> myset(num.begin(), num.end());for_each(myset.begin(), myset.end(), [](const int& out){cout << out << " "; });

完整的最小堆,从小到大频率输出字符

struct cmp{bool operator()(const pair<int, char>&l, const pair<int, char>&r){return l.first > r.first;}};string frequencySort(string s) {map<char, int> strMap;for (auto ch : s){strMap[ch]++;}        //注意定义的方式,同时自定义第三个函数priority_queue<pair<int, char>, vector<pair<int, char>>, cmp> priQue;for (auto tempMap : strMap){priQue.push(make_pair(tempMap.second, tempMap.first));}string outstr;while (!priQue.empty()){pair<int, char> temp = priQue.top();outstr.append(temp.first, temp.second);priQue.pop();}return outstr;return 0;}



0 0
原创粉丝点击