【问题标题】:Intersection of two arrays with its frequency两个阵列的交点及其频率
【发布时间】:2022-07-22 17:53:16
【问题描述】:

锻炼 在两个数组的交集问题中,我们给了两个数组,我们需要打印它们的交集(公共元素)。


public class IntersectionOfTwoArrays {
    private static void printIntersection(int[] arr1, int[] arr2) {
        HashMap<Integer, Integer> map = new HashMap<>();
        // Build the frequency map for arr1
        for (int i = 0; i < arr1.length; i++) {
            if (map.containsKey(arr1[i])) {
                map.put(arr1[i], map.get(arr1[i]) + 1);
            } else {
                map.put(arr1[i], 1);
            }
        }
        // Traverse the elements of arr2 one by one
        for (int i = 0; i < arr2.length; i++) {
            // If the map contains current element
            if (map.containsKey(arr2[i])) {
                // Reduce the frequency by 1
                int freq = map.get(arr2[i]);
                freq--;
                // If freq becomes 0, remove the element from the map
                if (freq == 0) {
                    map.remove(arr2[i]);
                } else {
                    map.put(arr2[i], freq);
                }
                // Print the element
                System.out.print(arr2[i] + " ");
            }
        }
        System.out.println();
    }

我发现这个实现对我来说非常好。 不幸的是,我不明白第二部分中删除数量的频率。

如果地图包含来自第一个数组的键,它应该有频率一,那么如果再次发生它应该去+1,为什么我们要删除存在于第一个地图中的元素?

        for (int i = 0; i < arr2.length; i++) {
            // If the map contains current element
            if (map.containsKey(arr2[i])) {
               // Reduce the frequency by 1
                int freq = map.get(arr2[i]);
                freq--;
                // If freq becomes 0, remove the element from the map
                if (freq == 0) {
                    map.remove(arr2[i]);
                } else {
                    map.put(arr2[i], freq);
                }

【问题讨论】:

    标签: java


    【解决方案1】:

    第一个循环计算arr1 元素在Map&lt;Integer, Integer&gt; 中的频率。第二个循环考虑arr2,我们希望在其中找到相同的元素。

    重要的是,我们不希望包含arr2 的元素比我们在arr1 中发现的更多。例如值2 包含在arr1 中三次,arr2 中包含四次。交集应该只有三个2。为了解决这个问题,我们降低了第二个循环的频率。

    arr1={2,2,2]arr2=[2,2,2,2] 为例,说明清楚。 -&gt; 之前的数字是地图的键,-&gt; 之后的数字是频率。在第一个循环中,频率只是在三次迭代中增加到三次。

    循环 1:

    element 0: 2 -> 1
    element 1: 2 -> 2
    element 2: 2 -> 3
    

    循环2:

    element 0: 2 -> 3-1; print("2")
    element 1: 2 -> 2-1; print("2")
    element 2: 2 -> 1-1; print("2")
    element 3: 2 -> 0; 
    

    如您所见,循环打印出三倍的值2,这是正确的交集。最后两个没有打印,因为我们知道在arr1 中只包含三个2

    【讨论】:

      【解决方案2】:

      需要从频率图中移除以保持匹配值 Vi 最小频率 min(F1i, F2i)在两个数组中。

      假设array1[0, 1, 0]array2[1, 0, 1]

      那么迭代第一个数组后的频率图看起来像{0=2, 1=1},在计算array2中的第一个1后,频率减少到0,键1从图中删除,因此@ 987654329@ 是false 并且在array2 中随后出现的1 被排除在交集之外。


      实际上可以跳过从地图中删除,如果剩余频率仅与 0 进行比较,如下所示。

      另外,关于实现:使用方法Map::merge可能有助于使方法更简洁:

      private static void printIntersection(int[] arr1, int[] arr2) {
          HashMap<Integer, Integer> map = new HashMap<>();
          // Build the frequency map for arr1
          for (int i = 0; i < arr1.length; i++) {
              map.merge(arr1[i], 1, Integer::sum); // adding occurrence in arr1
          }
      
          // Traverse the elements of arr2 one by one
          for (int i = 0; i < arr2.length; i++) {
              // subtracting occurrence in arr2
              if (map.merge(arr2[i], -1, Integer::sum) >= 0) {
                  System.out.print(arr2[i] + " ");
              }
          }
          System.out.println();
      }
      

      【讨论】:

      • 如果我有示例 arr1 [1, 2, 2] ; arr2[1, 3, 3] 当这段代码出现时: int freq = map.get(arr2[i]);, 然后 freq-- 我将从地图中删除元素,所以据我了解不会出现在结果中,所以数字 1 没有出现,但它应该出现。
      • 在此示例中,数字 1 应出现在输出中,因为在第一个数组之后出现了一次:{1=1, 2=2},然后在 arr2 中检测到 1, freq-- -> freq = 0,并且该条目从映射{2=2}中删除。之后arr2 不包含1,但即使包含,地图也不再有键1
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多