【发布时间】:2020-05-05 13:58:10
【问题描述】:
我正在做以下编程练习:Numericals of a String。声明是:
给你一个输入字符串。
对于字符串中的每个符号,如果它是第一个出现的字符, 将其替换为“1”,否则将其替换为您的次数 已经看过了...
但是您的代码会性能足够吗?例子:
input = "Hello, World!" result = "1112111121311" input = "aaaaaaaaaaaa" result = "123456789101112"字符串中可能有一些非ASCII字符。
注意:不会有 int 域溢出(字符出现将 少于 20 亿)。
我已经写了以下答案:
import java.util.*;
import java.util.stream.*;
public class JomoPipi {
public static String numericals(String s) {
System.out.println("s: "+s);
Map<String, Long> ocurrences = Arrays.stream(s.split("")).
collect(Collectors.groupingBy(c -> c,
Collectors.counting()));
System.out.println("ocurrences: "+ocurrences.toString());
StringBuilder result = new StringBuilder();
for(int i = s.length()-1; i >= 0; i--){
String c = String.valueOf(s.charAt(i));
result.append(ocurrences.get(c) + " ");
ocurrences.put(c, ocurrences.get(c)-1);
}
System.out.println("result: "+result.toString());
String[] chars = result.toString().split(" ");
Collections.reverse(Arrays.asList(chars));
String sorted = String.join("",chars);
System.out.println("sorted: "+sorted);
return sorted;
}
}
但是,当输入字符串很大时,它会超时(执行时间在 16000 毫秒以上)。
要查看它是如何工作的,有一个带有非常小的输入字符串的跟踪:
s: Hello, World!
result: 1 1 3 1 2 1 1 1 1 2 1 1 1
sorted: 1112111121311
此外,我还写了以下替代答案:
import java.util.*;
import java.util.stream.*;
public class JomoPipi {
public static String numericals(String s) {
System.out.println("s: "+s);
Map<String, Long> ocurrences = Arrays.stream(s.split("")).
collect(Collectors.groupingBy(c -> c,
Collectors.counting()));
String[] result = new String[s.length()];
for(int i = s.length()-1; i >= 0; i--){
String c = String.valueOf(s.charAt(i));
result[i] = String.valueOf(ocurrences.get(c));
ocurrences.put(c, ocurrences.get(c)-1);
}
System.out.println("result: "+Arrays.toString(result));
return String.join("",result);
}
}
即便如此,它仍然超时。
这是一个带有小输入字符串的跟踪:
s: Hello, World!
result: [1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 3, 1, 1]
我们如何改进解决方案?哪种算法可以更好地处理非常大的输入字符串?为了改进这个答案,我们应该调试和避免的瓶颈在哪里?
为了尝试自己解决,我已阅读:
- How do I count the number of occurrences of a char in a String?
- Hashmap implementation to count the occurrences of each character
- How do I reverse an int array in Java?
- https://www.codewars.com/kata/5b4070144d7d8bbfe7000001/discuss
- HashMap to return default value for non-found keys?
- What is the difference between putIfAbsent and computeIfAbsent in Java 8 Map ?
编辑:这里我们有一个基于@khelwood 建议的答案:
import java.util.*;
import java.util.stream.*;
public class JomoPipi {
public static String numericals/*????->????*/(String s) {
Map<String, Integer> ocurrences = new HashMap<String,Integer>();
StringBuilder result = new StringBuilder();
for(int i = 0; i < s.length(); i++){
String c = String.valueOf(s.charAt(i));
ocurrences.putIfAbsent(c, 0);
ocurrences.put(c,ocurrences.get(c)+1);
result.append(ocurrences.get(c));
}
return result.toString();
}
}
【问题讨论】:
-
从说明看来,您应该能够只遍历字符串一次,同时保持字符数。通过首先计算字符然后向后遍历字符串,您已经使它变得更加困难。
标签: java string algorithm performance char