基于最频繁的char计数的Java字符串操作

时间:2016-02-05 23:08:03

标签: java string algorithm data-structures

在最近的采访中,我被要求为下面的String操作程序找到解决方案。 给定一个字符串s,表示最常用的字符为1,第二个最常用的字符为01,第三个为001等。

  

如果String是" marrymyyyr",那么输出应为:

     

每个字符的字符数为m:2,a:1,r:3,y:4最高计数   number为4,因此具有该计数的字符应打印1   在该char的位置,具有计数3的char应打印为01   取而代之的是等等。

     

输出:001(m)0001(a)01(r)01(r)1(y)001(m)1(y)1(y)1(y)01(r)

我使用HashMap跟踪每个角色的计数。然后我无法解决问题。我知道我必须实现一些机制,将哈希/映射应用于hashmap,这是基于最常见的char映射,其对应结果字符串与" 1" " 0"并使用映射的结果字符串而不是该字符串打印char。

1 个答案:

答案 0 :(得分:0)

你说你用HashMap。如果您将地图创建为Map<Character, AtomicInteger>,则可以直接更新该值,而不会影响地图。

这样可以提高过程计数步骤的性能,但也可以让您更换&#34; count&#34;值,其值表示要为字符打印的0的数量,即a&#34; rank&#34;。

示例:如果计数为m:2, a:1, r:3, y:4(来自问题),则会对列表降序排序(y:4, r:3, m:2, a:1),然后使用递增排名替换计数:y:0, r:1, m:2, a:3

如果您使用LinkedHashMap,那么具有相同计数的多个字符将按首次出现的顺序排列。

使用这些排名,您现在可以转换输入。 (以下是适用于任何Java版本。在Java 8上,lambdas会大量减少代码。我将把它作为练习留给你。)

private static String test(String input) {
    char[] chars = input.toCharArray();

    // Collect chars with count of occurrences
    Map<Character, AtomicInteger> charMap = new LinkedHashMap<>();
    for (Character c : chars) {
        AtomicInteger count = charMap.get(c);
        if (count == null)
            charMap.put(c, new AtomicInteger(1));
        else
            count.incrementAndGet();
    }

    // Sort char/count pairs by count (descending)
    @SuppressWarnings("unchecked")
    Entry<Character, AtomicInteger>[] charArr = charMap.entrySet().toArray(new Map.Entry[charMap.size()]);
    Arrays.sort(charArr, new Comparator<Entry<Character, AtomicInteger>>() {
        @Override
        public int compare(Entry<Character, AtomicInteger> e1, Entry<Character, AtomicInteger> e2) {
            return Integer.compare(e2.getValue().intValue(), e1.getValue().intValue()); // descending
        }
    });

    // Replace "count" with "rank" (this updates values in charMap)
    for (int i = 0; i < charArr.length; i++)
        charArr[i].getValue().set(i);

    // Generate result
    StringBuilder buf = new StringBuilder();
    for (Character c : chars) {
        int rank = charMap.get(c).intValue();
        while (rank-- > 0)
            buf.append('0');
        buf.append('1');
        buf.append('(').append(c).append(')'); // Remove?
    }
    return buf.toString();
}

<强>测试

System.out.println(test("marrymyyyr"));

<强>输出

001(m)0001(a)01(r)01(r)1(y)001(m)1(y)1(y)1(y)01(r)

问题的措辞使得听起来像字母应该被替换(&#34;取代&#34;)。如果是,请注释掉或删除标有// Remove?

的行

<强>输出

00100010101100111101