leetcode 451 根据字符出现频率排序 根据map中的value重写排序

先上答题截图,在写思路,哈哈哈哈啊

451. 根据字符出现频率排序

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:
"tree"

输出:
"eert"

解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入:
"cccaaa"

输出:
"cccaaa"

解释:
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入:
"Aabb"

输出:
"bbAa"

解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。

今天的题目不难,思路很好想,官方题解给了两种思路,不过我想到得是第一种思路,一般为了方便和简单我很少回去考虑官方题解的第二种思路那样得桶排序,而是简单的去用map存储一下每个字符出现的频率然后排个序,最后进行打印,思路很简单,然后我写这篇博客的主要目的是总结自己关于map根据键和值排序的方法,先上解题代码吧,上完代码之后在总结map上根据键和值的排序语法。

老实交代解题代码是抄官方题解的,因为我想到思路但是不会java中关于map键值排序的那部分语法,所以下面来总结了。

关于map中对 map的values进行排序

第一种方法:最简洁

一上面的这个力扣题为例可以先建立一个键为 Character  类型  值为 Integer 类型的 HashMap,然后使用 List 集合去存储 map里面的键,最后使用简洁的  lambda表达式 语法进行排序,也是上面的给的那种形式

Map<Character, Integer> map = new HashMap<Character, Integer>();

for (int i = 0; i <  s.length(); ++i)        map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);

List<Character> list = new ArrayList<Character>(map.keySet());

Collections.sort(list, (a, b) -> map.get(b) - map.get(a));

这里对上面的代码进行一些解释(仅对于可能是新手入门算法,虽然我也是新手不算入门,哈哈哈哈哈 >=<),因为我之前刚开始刷题的时候很多东西看不懂,很是头疼,经常要百度很多函数的用法,所以。。。。。。。很能理解那种烦躁的心情,正好今天没事顺便来写点

Character,Integer  首先Map 或者 List这样的容器里面只能放非简单基本类型的变量所以这里面不能用char 和 int,   第二点就是s.charAt(i)  是取了字符串s中的 index为 i 位置的字符,     map.getOrDefault(s.charAt(i), 0)函数是如果没在map中找到s.charAt(i) 字符的键的话,就设置这个字符的键的值为默认0,如果找到了就返回原本在map中s.charAt(i)字符对应的值。第三个一般对于容器来说排序用的  Collections.sort() 函数,而对于其他一般基本类型的数组,如 int [ ] 则使用Arrays.sort()函数, 最后 (a, b)-> map.get(b) - map.get(a) 是属于lambda表达式语法,这个语法如果不懂建议需要百度一下,这上面的使用  map.get(b) - map.get(a)  的作用是进行降序排序,如果要进行升序排序的话需要把a和b换一个位置  ,换成  map.get(a) - map.get(b)

第二种方法:比较常规

这种不通过使用最新的lambda表达式语法去进行排序,而是使用最常规传统的改写compare()函数的方法,不过这里又用了另外一种java的比较新的语法,匿名类(如果有看不懂或者看不习惯这中语法的朋友建议去百度学习一下或者可以自己重写类去实现Comparator接口并且改写里面的compare()函数这个方法大概代码我会放在下面介绍

Map<Character, Integer> map = new HashMap<Character, Integer>();

for (int i = 0; i <  s.length(); ++i)        map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);

List<Character> list = new ArrayList<Character>(map.keySet());

Collections.sort(list, new Comparator<Character>(){

        public int compare(Character a, Character b){

                return map.get(b) - map.get(a);

        }

});

这种方法和第一种方法的不懂只在于重写排序的时候第一种方法使用lambda语法实现的这种是用匿名类实现的。

第三种方法: 更传统

新建类实现Comparator接口重写compare()函数去实现

public class SortMapByValue {

    public static Map<K, V> sortMap(Map<K, V> unsortedMap) {
        Comparator<K> comparator = new ValueComparator<K, V>(unsortedMap);
        TreeMap<K, V> result = new TreeMap<K, V>(comparator);
        result.putAll(unsortedMap);

        return result;
    }
}

class ValueComparator<K, V extends  Comparable<V>> implements Comparator<K> {
    HashMap<K, V> map = new HashMap<K, V>();

    public ValueComarartor(HashMap<K, V> map) {
        this.map.putAll(map);
    }

    @Override
    public int compare(K s1, K s2) {
        return map.get(s1).compareTo(map.get(s2));
    }
}

上面代码只是作为摸板仅作参考

当然出了针对这个力扣题可以使用更轻量的List<Character>  更多情况还可以直接使用传入整个map去进行重写排序函数

Map<Character, Integer> map = new HashMap<Character, Integer>();

for (int i = 0; i <  s.length(); ++i)        map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);

List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(map.entrySet());

Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>(){

            public int compare(Map.Entry<Character, Integer> a, Map.Entry<Character, Integer> b){

                return b.getValue() - a.getValue();

            }

        });

这种方法相对于上面比较就时间和空间而言过于厚重,能使用上面的方法时建议使用上对面的那些方法

最后说一下重写compare( ) 函数时除了这种数值型的可以直接用 “ - ”减号这个运算符去实现,更多时候还可以用 compareTo( ) 这个函数去实现,而且这个函数不仅可以用于数值型的参数还对于许多非数值型的参数类型也可以做比较,当然具体的用法的话如果不熟悉还是建议大家百度一下

这里举一下对于方法一种map.get(b) - map.get(a)  其实与使用map.get(b).compareTo(map.get(a))的效果是一样的。

最后先写到这里,下午写了一下午,然后刚才屏幕熄屏了,怎么都打不开,下的我以为要强制关机,幸好没有,但是打开的时候电脑网断了,浏览器也自己掉了,吓得我人都傻了,幸好这个服务器上面有草稿记录,不然真的一下午白费了,这个真的不错,最后收尾了,我要特别强调一句,我的水平不高,文章中有些错的地方欢迎各位大佬们评论指导订正,我看到一定去学习并改正,最后特别感谢各位读者大佬们的观看,谢谢,也希望你们辛苦的阅读时间能有所收获,祝读者大佬门学习开心   > = <  

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tp_0moyi0

新手入行,慢慢学习,慢慢积累

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值