计算数组中出现了多少对数字

Count how many pairs of a number appear in an array

假设数组:

array = {1,2,1,2,1,3,2,1};

我希望输出为:

2 pairs of number 1, 1 pair of number 2

为此我创建了一个哈希 table。代码:

class Trail{
    static void countFreq(int arr[], int n)
    {
        Map<Integer, Integer> mp = new HashMap<>();
 
        // Insert elements into HashTable while avoiding overwriting:
        for (int i = 0; i < n; i++)
        {
            // This part is to avoid overwriting:
            if (mp.containsKey(arr[i]))
            {
                mp.put(arr[i], mp.get(arr[i]) + 1);
            }
            else
            {
                mp.put(arr[i], 1);
            }
        }
        // Traverse through map and print frequencies
        for (Map.Entry<Integer, Integer> entry : mp.entrySet())
        { 
            System.out.println(entry.getKey() + " " + entry.getValue());
            
        }
         
    }

    public static void main(String[] args) {

        int arr[] = {1,2,1,2,1,3,2,1};
        int n = arr.length;
        countFreq(arr, n);
    }
}

不确定下一步要做什么才能打印出所需的输出。卡在这个简单的部分好久了

最简单的做法是使用 Map<Integer, Long> 并计算频率。

  • 流式传输数组
  • 将其装箱(转换为 Integer 对象)
  • 根据值 a
  • 分组
  • 并计算该值的出现次数
  • 在地图中,k是值,v是计数
  • 还添加了逻辑以更正数字复数。
int[] vals  = {1,2,1,2,1,3,2,1};
Arrays.stream(vals).boxed().collect(
        Collectors.groupingBy(a -> a, Collectors.counting()))
        .forEach((k, v) -> {
            if (v > 1) {
                System.out.println(v / 2 + " pair"
                        + ((v > 3) ? "s" : "") + " of " + k);
            }
        });

打印

2 pairs of 1
1 pair of 2

请注意,这利用了整数除法并舍弃了分数。所以任何奇数 n 将具有 (n-1)/2 对的值。


频率的计算似乎没问题,只需要解决打印部分。要获得对数,将频率除以 2(或右移 1),如果对数为 0 则跳过(根据预期输出)。

打印应该移到单独的方法中:

static void printFreq(Map<Integer, Integer> mp) {
    boolean addComma = false;
    for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
        int pairs = entry.getValue() / 2;
        if (pairs < 1) {
            continue; // skip 0 pairs
        }
        if (addComma) {
            System.out.print(", ");
        }
        String p = pairs > 1 ? " pairs " : " pair ";
        System.out.print(pairs + p + "of number " + entry.getKey());
        addComma = true;
    }        
    System.out.println();    
}

但是,Stream API 可用于此类任务:

  • 使用 vararg int ... arr 以更方便的方式传递整数值数组(n 因为数组长度是多余的)
  • 使用Collectors.groupingByCollectors.summingInt(或Collectors.counting)计算原始频率
  • 计算对数
  • 将每个键值对映射到字符串
  • 使用 Collectors.joining
  • 连接字符串
static void countFreq(int ... arr) {
    String message = Arrays.stream(arr)
        .boxed()
        .collect(Collectors.groupingBy(
            x -> x,
            Collectors.summingInt(x -> 1)
        )) // Map<Integer, Integer>
        .entrySet()
        .stream()
        .peek(e -> e.setValue(e.getValue() / 2))
        .filter(e -> e.getValue() > 0)
        .map(e -> String.format("%d %s of number %d", 
            e.getValue(), e.getValue() > 1 ? "pairs" : "pair", e.getKey()
        ))
        .collect(Collectors.joining(", "));
    System.out.println(message);
}

输出(在两种情况下):

2 pairs of number 1, 1 pair of number 2