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

时间:2016-11-14 19:10:28

标签: java algorithm sorting hashmap

我试图用Java解决这个问题。目标是根据字符的频率按递减顺序对字符串进行排序。例如" Aabb"将成为" bbaA"或" bbAa"。我已经实现了一个有效的解决方案但它在O(n ^ 2)中。我想知道是否有人有更好,更优的解决方案。 这是代码:

{{1}}

3 个答案:

答案 0 :(得分:2)

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

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

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

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

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

答案 1 :(得分:0)

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

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

return builder.toString();

如何按频率对元素进行排序还有其他一些想法。

  1. 使用排序算法对元素O(nlogn)进行排序
  2. 扫描已排序的数组并构建元素和计数的2D数组 为O(n)。
  3. 根据计数O(nlogn)

    对2D数组进行排序

    输入2 5 2 8 5 6 8 8

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

    现在将2D数组构造为

    2,2

    5,2

    6,1

    8,3

    按计数排序

    8,3

    2,2

    5,2

    6,1

  4. copyright

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

答案 2 :(得分:0)

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

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