任务是编写一个计算最常见数字的代码。例如,A[1,2,4,4,4,5,6,7,4]
将是4
与4
计数。我需要保持这段代码简单,因为我只是尝试将我的代码从算法和数据结构实现到java。
我的想法是这个,但不知怎的,我从未达到最后的条件。
public class countingNumbers{
public static void main(String []args){
System.out.print(counting(new int[]{1,1,1,2,3,4,4,4,4,5,6}));
}
public static int counting(int[] x){
int memory = 0;
int counter = 0;
int mostCommon = 0;
for(int i = 0; i < x.length-1;i++){
for(int j = i+1; j < x.length-1; j++){
if(x[i] == x[j]){
counter = counter +1;
}
else if(j == x.length-1 && counter >= memory){
mostCommon = x[i];
memory = counter;
counter = 0;
}
}
}
return mostCommon;
}
}
- >提前感谢您的所有答案,我很感激。我只是在寻找不用于流,api或其他什么的逻辑。我试过手写代码,java中的实现只是为了自己看看它是否成功但不幸的是它没有。
更新 - 正确的解决方案是:
public class countingNumbers {
public static void main(String []args){
System.out.print(counting(new int[]{1,2,2,2,6,2}));
}
public static int counting(int[] x){
int memory = 0;
int counter = 1;
int mostCommon = 0;
for(int i = 0; i < x.length;i++){
for(int j = i+1; j <= x.length-1; j++){
if(x[i] == x[j]){
counter = counter + 1;
}
if(j == x.length-1 && counter >= memory){
mostCommon = x[i];
memory = counter;
counter = 1;
}
}counter = 1;
} return memory;
}
}
我将流数组并将其收集到映射中,计算每个元素的出现次数,然后返回具有最高计数的数组:
/**
* @return the element that appears most in the array.
* If two or more elements appear the same number of times, one of them is returned.
* @throws IllegalArgumentException If the array is empty
*/
public static int counting(int[] x){
return Arrays.stream(x)
.boxed()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElseThrow(() -> new IllegalArgumentException("x must not be empty"));
}
如果你擅长流式api ..或仅仅是为了教育目标,有groupingBy
的流解决方案:
Integer[] arr = {1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 6};
Map<Integer, Long> map = Arrays.stream(arr)
.collect(Collectors.groupingBy(o -> o, Collectors.counting()));
Integer common = map.entrySet().stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.map(Map.Entry::getKey).get();
System.out.println(common);
更新:如果流与您无关:
它可以通过foor-loop
完成,但在这里使用Map
仍然很方便:
public static int counting(int[] x) {
Map<Integer, Long> map = new HashMap<>(); // key is a number, value is how often does it appear in the array
for (int number : x) {
if (map.get(number) != null) {
map.put(number, map.get(number) + 1);
} else {
map.put(number, 1L);
}
}
return Collections.max(map.entrySet(), Map.Entry.comparingByKey()).getKey();
}
注意:有很多方法可以从与最大值关联的地图中获取关键字。看到这里找到最合适的方式:Finding Key associated with max Value in a Java Map
if else
语句也可以用java8中的merge方法替换:
map.merge(number, 1L, (a, b) -> a + b);
看看这两行:
for (int j = i + 1; j < x.length - 1; j++) {
和
} else if (j == x.length - 1 && counter >= memory)
你循环,而j
严格小于x.length - 1
,但你的else if
只在j
完全等于x.length - 1
时触发。所以你永远不能在你的else if
块中找到代码。
此外,您的计数器应该从一开始,因为您正在计算与您正在查看的条目匹配的条目数,因此您跳过计算第一个条目。但是既然你没有在任何地方输出计数器,我猜它并不是非常相关。
因此,要修复代码,请更改内部for循环以转到j <= x.length - 1
。
声明两个变量以保存最常见的数字及其频率:
int mostCommon =Integer.MIN_VALUE;
int highFreq = 0;
迭代你的阵列。对于每个元素,再次遍历数组并计算其频率。如果当前计数大于highFreq
更新mostCommon
,则将其设置为当前元素并设置highFreq
当前计数。例:
public class countingNumbers{
public static void main(String[] args) {
int[] res = counting(new int[]{6, 4, 5, 4, 5, 6, 4, 3, 2});
System.out.println("most common number is: " + res[0] + " with " + res[1] + " counts");
}
public static int[] counting(int[] x) {
int mostCommon = Integer.MIN_VALUE;
int highFreq = 0;
for (int i = 0; i < x.length; i++) {
int currFreq = 0;
for (int j = 0; j < x.length; j++) {
if (x[i] == x[j]) {
currFreq++;
}
}
if (highFreq < currFreq) {
highFreq = currFreq;
mostCommon = x[i];
}
}
return new int[]{mostCommon, highFreq};
}
}