按频率对字符排序Java(最佳解决方案)

按频率对字符排序Java(最佳解决方案),java,algorithm,sorting,hashmap,Java,Algorithm,Sorting,Hashmap,我试图用Java解决这个问题。目标是根据字符的频率按降序对字符串进行排序。例如,“Aabb”将是“bbaA”或“bbaA”。我已经实现了一个有效的解决方案,但它处于O(n^2)状态。我想知道是否有人有更好、更好的解决方案。 代码如下: public class Solution { public String frequencySort(String s) { Map<Character,Integer> map =new HashMap<Charac

我试图用Java解决这个问题。目标是根据字符的频率按降序对字符串进行排序。例如,“Aabb”将是“bbaA”或“bbaA”。我已经实现了一个有效的解决方案,但它处于O(n^2)状态。我想知道是否有人有更好、更好的解决方案。 代码如下:

public class Solution 
{
    public String frequencySort(String s) 
   {
    Map<Character,Integer> map =new HashMap<Character,Integer>();
    for(int i=0;i<s.length();i++)
    {
        if(map.containsKey(s.charAt(i)))
            map.put(s.charAt(i),map.get(s.charAt(i))+1);
        else
            map.put(s.charAt(i),1);
    }

    List<Map.Entry<Character,Integer>> sortedlist = new ArrayList<>(map.entrySet());
    Collections.sort(sortedlist, new Comparator<Map.Entry<Character,Integer>>() {

    @Override
    public int compare(Map.Entry<Character, Integer> o1,
            Map.Entry<Character, Integer> o2) {
        return o2.getValue() - o1.getValue();
    }
    });

    String lastString="";
    for (Map.Entry<Character,Integer>  e : sortedlist) 
    {
        for(Integer j=0;j <  e.getValue();j++)
           lastString+= e.getKey().toString();
    }
    return lastString;
   }
}
公共类解决方案
{
公共字符串频率排序(字符串s)
{
Map Map=newhashmap();

对于(int i=0;i由于字符串串联,您的代码无法通过,请改用StringBuilder,我打赌您会通过

StringBuilder builder = bew StringBuilder();
builder.append(e.getKey());

return builder.toString();
关于如何按频率对元素进行排序,还有一些其他的想法

  • 使用排序算法对元素进行排序O(nlogn)
  • 扫描已排序的数组,并构建元素和计数的二维数组 O(n)
  • 根据计数O(nlogn)对2D数组进行排序

    输入2 5 2 8 5 6 8 8

    分类后我们得到 2 2 5 6 8 8 8

    现在将二维数组构造为

    2,2

    5,2

    6,1

    8,3

    按计数排序

    8,3

    2,2

    5,2

    6,1


  • 按照链接查看其他可能的方法。

    您的算法实际上是
    O(n)
    (谢谢,两次!):

    • 构建计数图是
      O(n)
      ,其中
      n
      是输入的长度
    • 条目列表的排序是
      O(m log m)
      ,其中
      m
      是输入中唯一字符的数量
    • 重新生成排序的字符串是
      O(n)
    虽然最慢的步进幅度可能是排序,但当输入非常大时,它很可能不是主要操作。“可能”,因为
    m
    受字母表大小的限制,通常预期字母表的大小比非常大的输入的大小小得多。因此
    O的总体时间复杂度(n) 

    可以进行一些较小的优化,但不会改变复杂性的顺序:

    • 您可以首先从输入字符串获取字符数组。它使用更多内存,但您将保存
      .charAt
      的边界检查,该数组在以后的步骤中可能会很有用(请参见下文)
    • 如果您知道字母表的大小,那么可以使用
      int[]
      而不是哈希映射
    • 您可以写入字符数组并返回
      新字符串(chars)
      ,而不是手动重建排序后的字符串并进行字符串连接

    如果必须根据字符的频率显示字符,我们可以使用Python中的映射或字典。 我正在使用Python解决这个问题:

    # sort characters by frequency
    
    def fix(s): 
        d = {}
        res=""
        for ch in a: d[ch] = d.get(ch,0)+1
        # use this lambda whenever you have to sort with values
        for val in sorted(d.items(),reverse = True,key = lambda ch : ch[1]):
            res = res + val[0]*val[1]
        return res    
    
    
    a = "GiniGinaProtijayi"
    print(fix(a))    
    
    方法2:使用collections.Counter().most_common()


    嗯,从技术上讲,这不是
    O(n^2)
    。这里可能有一些小的优化,但是没有办法低于
    O(n log n)
    ,您已经在那里了。@Paul在Java中没有更好的方法了吗?由于时间限制,他不接受这个答案。确保有办法改进代码。将
    Map
    替换为
    Map
    ,这样您就可以使用
    ++
    更新整数值,而不是取消装箱和重新装箱
    integer
    对象。如果在使用Java 8时,使用
    merge()
    方法。不要使用
    string+=string
    ,而是使用
    StringBuilder
    。出于与上述相同的原因,将循环更改为
    int
    ,而不是
    Integer
    。要创建一个N倍于同一字母的字符串,请创建
    char[N]
    并使用
    数组。fill()
    将字母分配给所有元素。您考虑过树形图吗?它会为您自动排序,但我不能完全确定是更快还是更快not@HiradRoshandel嗯,没有一种算法具有更好的时间复杂度(假设您的hashmap在
    O(1)中工作)
    。这并不意味着您的代码无法优化。这意味着您无法提高渐进时间复杂性,但有很多方法可以改进此代码。对列表排序不是
    O(n log n)
    ,而是
    O(m log m)
    其中
    m
    是唯一字符的数量,即
    m在最后一个项目符号中建议使用完整的
    char[]
    。这是一个比使用
    StringBuilder
    更好的解决方案。从第一步开始重用数组只是锦上添花。感谢Andreas的精确性(以及向上的投票),我只是懒得说出来,但你是对的,这一点很重要。你没有抓住最后一句话的要点。整体算法是
    O(n)
    ,因为
    O(m log m)
    在较高的
    n
    值时成为常数,因此从方程中排除。想想
    n=100000
    (线性),具有
    m=60
    (常数)。@Andreas我不确定它是否在O(n)中运行。由于时间限制,正在拒绝我的解决方案。不过我理解你的观点
    # sort characeters by frequency
    a = "GiniGinaProtijayi"
    
    
    def sortByFrequency(a):
        aa = [ch*count  for ch, count in collections.Counter(a).most_common()]
        print(aa)
        print(''.join(aa))
    
    
    sortByFrequency(a)