如何有效地在映射中包含最高重复值的约束条件下找到最高价值的最低关键字?

时间:2019-10-09 07:37:00

标签: java dictionary hashmap java-stream

由于这个特殊的问题,我提出了疑问:

https://www.hackerrank.com/challenges/migratory-birds/problem?h_r=next-challenge&h_v=zen&h_r=next-challenge&h_v=zen&h_r=next-challenge&h_v=zen

我知道可以通过以下方式轻松解决此问题:

  1. 将频率存储在地图中
  2. 初始化两个临时变量a,b
  3. 开始循环

     - Store the current max value & key to a,b
     - If we find similar value: store the lowest key pair to b.
    
  4. 返回b值

*但我不想这样做。我想使用Streams *

解决Map问题

输入,arr包含11个值, 1 2 2 2 3 4 5 5 4 3 4

输出应为 2

说明1

不同类型的鸟类以下列频率出现:

  • 类型1:1
  • 类型2:3
  • 类型3:2
  • 类型4:3
  • 类型5:2

两种类型的频率为3,而较低的是2型。

我尝试了下面的有效代码,但我不知道如何。我使用了一个max函数,期望我会得到一个错误,因为我的示例中有两个带有最大值3的值。

但是看看我使用了 Collections.max 的migratoryBirds()函数,该查询向我返回了具有最高值的最低键的地图条目。

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

public class Solution{

    // Complete the migratoryBirds function below.
    static int migratoryBirds(List<Integer> arr) {
        Map<Integer,Integer> map = new HashMap<>();
        int temp=0;
        for(int val : arr){
            if(map.containsKey(val)){
                temp=map.get(val);
                map.put(val,temp+1);
            }else{
                map.put(val,1);
            }
        }
        Map.Entry<Integer,Integer> maxEntry = Collections.max(map.entrySet(),
                (e1, e2) -> e1.getValue().compareTo(e2.getValue()));
        return maxEntry.getKey();
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

        int arrCount = Integer.parseInt(bufferedReader.readLine().trim());

        List<Integer> arr = Stream.of(bufferedReader.readLine().replaceAll("\\s+$", "").split(" "))
                .map(Integer::parseInt)
                .collect(toList());

        int result = migratoryBirds(arr);

        bufferedWriter.write(String.valueOf(result));
        bufferedWriter.newLine();

        bufferedReader.close();
        bufferedWriter.close();
    }
}

任何人都可以向我解释为什么我得到了预期的结果,并建议使用Map Streams的一种合适的替代方法。

对不起,如果我的问题很奇怪,我喜欢研究所有可能的方式。

2 个答案:

答案 0 :(得分:0)

您可能会使用的是:

int minKeyWithMaxValueEntry = map.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, 
                Integer::min, TreeMap::new))
        .lastEntry()
        .getValue();

详细说明collect操作:

  • 它将初始Map条目中的值存储为key,相应地,您条目中的每个键都将转换为结果Map的value

  • 由于可能有多个具有相同值的键,因此合并函数Integer::min在其中选择最小值。

  • 所有这些都存储在TreeMap中,以确保对生成的Map进行比较以比较其键。

  • 从中选择最后一个条目(对于初始Map中的最大值),并将最终Map中的值存储为输出。

答案 1 :(得分:0)

在id上对它们进行分组,以创建地图id-> count。然后找到最大数量,因为该地图是树状地图,所以最低ID将获胜

Stream.of(1, 2, 2, 2, 3, 4, 5, 5, 4, 3, 4 )
.collect(groupingBy(identity(), TreeMap::new, counting()))
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey).get();