【问题标题】:Sort Characters By Frequency Java (Optimal Solution)按频率对字符进行排序 Java(最佳解决方案)
【发布时间】:2017-03-28 12:34:17
【问题描述】:

我正在尝试使用 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;
   }
}

【问题讨论】:

  • 好吧,从技术上讲,这不是O(n ^ 2)。这里可能有一些小的优化,但没有办法低于O(n log n),你已经在哪里了。
  • @Paul 所以在 Java 中没有办法更好地做到这一点吗? leetcode.com/problems/sort-characters-by-frequency 由于时间限制不接受这个答案
  • 当然有办法改进代码。将Map&lt;Character,Integer&gt; 替换为Map&lt;Character,int[]&gt;,这样您就可以使用++ 更新整数值,而不是对Integer 对象进行拆箱和重新装箱。如果运行 Java 8,请使用 merge() 方法。不要使用string += string,而是使用StringBuilder。出于与上述相同的原因,将循环更改为int,而不是Integer。要创建 N 次相同字母的字符串,请创建 char[N] 并使用 Arrays.fill() 将字母分配给所有元素。
  • 你考虑过树形图吗?它会为你自动排序,虽然我不完全确定它是否更快
  • @HiradRoshandel 好吧,没有更好的时间复杂度算法(假设您的哈希图在O(1) 中工作。这并不意味着您的代码无法优化。这意味着您不会能够提高渐近时间复杂度,但有很多方法可以改进此代码。

标签: java algorithm sorting hashmap


【解决方案1】:

如果您必须根据频率显示字符,我们可以在 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))    

方法二:使用collections.Counter().most_common()

# 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)

【讨论】:

    【解决方案2】:

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

    • 构建计数图是O(n),其中n 是输入的长度
    • 对条目列表进行排序是O(m log m),其中m 是输入中唯一字符的数量
    • 重建排序后的字符串是O(n)

    虽然从数量上看最慢的步骤可能是排序,但当输入非常大时,它很可能不是主要操作。 “可能”,因为m 受字母表大小的限制,通常预期它比非常大的输入的大小要小得多。因此,O(n) 的整体时间复杂度。

    一些小的优化是可能的,但不会改变复杂性的顺序:

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

    【讨论】:

    • 对列表排序的不是O(n log n),而是O(m log m),其中m是唯一字符数,即m &lt;= n。随着n 上升到非常高的数字,m 将在取决于语言的点上达到稳定,例如对于英语,它将变平大约 60(26 个小写字母 + 26 个大写字母 + 1 个空格 + 一些标点符号)。因此,排序变得无关紧要,算法只是O(n)
    • 赞成在最后一个项目符号中建议完整的char[]。这是比使用StringBuilder 更好的解决方案。从第一步开始重用数组只是锦上添花。
    • 感谢 Andreas 的精确度(和赞成票),我只是懒得说出来,但你说得对,重要的是要提一下。
    • 你错过了最后一句话的重点。整体算法是O(n),因为O(m log m)n 值较高时变为常数,因此从等式中消除。想想n = 100000(线性)和m = 60(常数)。
    • @Andreas 我不确定它是否在 O(n) 中运行。 leetcode.com/problems/sort-characters-by-frequency 由于时间限制拒绝我的解决方案。不过我理解你的意思
    【解决方案3】:

    由于字符串连接,您的代码未通过,请改用 StringBuilder,我打赌您会通过。

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

    还有一些其他方法可以按频率对元素进行排序。

    1. 使用排序算法对元素进行排序 O(nlogn)
    2. 扫描排序后的数组并构造一个包含元素和计数的二维数组 O(n)。
    3. 按照计数O(nlogn)对二维数组进行排序

      输入 2 5 2 8 5 6 8 8

      排序后我们得到 2 2 5 5 6 8 8 8

      现在构造二维数组

      2, 2

      5、2

      6、1

      8、3

      按数量排序

      8、3

      2, 2

      5、2

      6、1

    copyright

    点击链接查看其他可能的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-06
      • 2012-04-27
      • 1970-01-01
      • 2020-09-25
      • 2023-03-21
      • 1970-01-01
      • 2020-06-13
      • 2011-07-08
      相关资源
      最近更新 更多