【问题标题】:How can I sort characters by frequency that can work with Java 7?如何按可用于 Java 7 的频率对字符进行排序?
【发布时间】:2020-09-25 12:29:55
【问题描述】:

我需要打印单词中出现的所有字母,重新排列以使出现频率最高的字母出现在开头。

如果存在出现次数相同的字母,则按字母排序后,首先显示最小的字母。

我已经尝试了一些方法,但我的输出超出了限制。

如何使用 BufferedWriter 使该解决方案运行得更快?我应该使用 HashMap 吗?

输入:指令

输出:iinnssttcoru

public class Main {
public static void main(String[] args) throws IOException {
String inputString;
BufferedReader reader = new BufferedReader(new 
InputStreamReader(System.in));
inputString = reader.readLine();
if(reader != null)
reader.close();
int[] letterArray = new int[26];
char[] letters = new char[26];
for(int i=0;i<=25;i++)
    letters[i] = (char)(97+i);
for(int i=0; i< inputString.length(); i++)
    letterArray[inputString.charAt(i) - 97] +=1 ;
for(int i=0; i<=24;i++)
    for(int j=i+1;j<=25;j++){
        if(letterArray[i] <letterArray[j] || (letterArray[i] == 
           letterArray[j] && letters[i] > letters[j])){
            int temp = letterArray[i];
            letterArray[i] = letterArray[j];
            letterArray[j] = temp;
            char temp2;
            temp2 = letters[i];
            letters[i] = letters[j];
            letters[j] = temp2;}
    }
  String outputString = new String();
    for(int i=0;i<=25;i++){
        for(int j = 0; j<letterArray[i]; j++)
            outputString += letters[i];}
  System.out.println(outputString);}
  }

我的第二个想法:

public class Main {
public static void main(String[] args) throws IOException {
String line;
BufferedReader reader = new BufferedReader(new 
InputStreamReader(System.in));
line = reader.readLine();

StringBuilder sb = new StringBuilder();
Map<Character, Integer> charCountMap = new HashMap<>();

int len = line.length();

for (int i = 0; i < len; i++) {
    char ch = line.charAt(i);
    charCountMap.put(ch, charCountMap.getOrDefault(ch, 0) + 1);
}

【问题讨论】:

  • HashMap&lt;Character,Integer&gt;是这个问题最明显的解决方案
  • BufferedReader 用于输入/输出,我不明白它如何帮助您加快算法速度。
  • @HomeIsWhereThePcIs 或 Map&lt;Integer, Integer&gt; 是否要支持补充平面的 Unicode 代码点,例如表情符号。
  • @GeorgeChetan 哪个部分阻止了你?构建一个Map 的字符频率,或者按频率对地图条目进行排序?
  • 另请注意:阅读有关正确 Java 代码缩进的信息。您应该将 { 大括号放在行尾,并且始终使用相同的缩进保持一致。这样的事情很重要。它们使您的代码易于阅读或难以阅读。

标签: java string algorithm sorting oop


【解决方案1】:

你可以实现一个实现Comparable接口的包装类:

class CharFreq implements Comparable<CharFreq>{

    final char c;
    int f = 0;

    CharFreq(char cc) {this.c = cc;}

    @Override
    public int compareTo(CharFreq that) {
        return this.f == that.f ? this.c - that.c : that.f - this.f;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        int ff = f;
        while (ff-- > 0) sb.append(c);
        return sb.toString();
    }
}

然后您填充地图并使用快速Collections.sort 对值进行排序:

String s = "instructions";
Map<Character, CharFreq> map = new HashMap<>();
for (char c : s.toCharArray()) {
    if (map.get(c) == null) {
        map.put(c, new CharFreq(c));
    }
    CharFreq cf = map.get(c);
    cf.f++;
}

List<CharFreq> list = new ArrayList<>(map.values());
Collections.sort(list);

for (CharFreq cf : list) {
    System.out.print(cf);
}

输出

iinnssttcoru

或者可以在不显式调用Collections.sort的情况下使用排序集:

Set<CharFreq> sorted = new TreeSet<>(map.values());
for (CharFreq cf : sorted) {
    System.out.print(cf);
}

【讨论】:

  • 这个return this.f == that.f ? this.c - that.c : that.f - this.f; 是一个糟糕的习惯。最好花点时间并根据需要返回 -1、1 或 0。以免没有经验的人采用这种做法并最终陷入困境。
  • 在这种减去两个字符或两个非负整数的特定情况下可能会出现什么样的麻烦?在String::compareTo 方法的JDK7JDK8 实现中使用了类似的方法。
  • 在这种情况下,没有。无论在 JDK 中如何使用,它仍然被认为是一种不好的做法。
猜你喜欢
  • 1970-01-01
  • 2020-02-06
  • 2020-06-13
  • 2021-11-22
  • 2023-03-21
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
相关资源
最近更新 更多