Home > Software design >  Intersection of two arrays with its frequency
Intersection of two arrays with its frequency

Time:03-07

Exercise In intersection of two arrays problem, we have given two arrays, we need to print their intersection(common elements).


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();
    }

I have found this implementation which looks for me really nice. Unfortunately I do not understand deleting quantity in frequency in second part.

If map contains key from first array it should have frequency one, then if happens again it shoould go 1, why we remove element which exist in first map?

        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);
                }

CodePudding user response:

The first loop counts the frequency of the elements of arr1 in a Map<Integer, Integer>. The second loop considers arr2, where we want to find the same elements.

The important part is that we don't want to include an element of arr2 more often than we found it in arr1. For example value 2 is included in arr1 three times and in arr2 four times. The intersection should only be three 2. In order to solve this problem, we decrease the frequency in the second loop.

Example for arr1={2,2,2] and arr2=[2,2,2,2] to make it clear. number before -> is the key of the map and number after -> is the frequency. In the first loop the frequency simply increases to three in three iterations.

Loop 1:

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

Loop2:

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; 

As you can see the loop prints three times the value 2, which is the correct intersection. The last two is not printed as we know that in arr1 only three 2 are included.

CodePudding user response:

Removal from the frequency map is needed to keep the matching value Vi by the minimal frequency min(F1i, F2i) in both arrays.

Let's assume, array1 is [0, 1, 0] and array2 is [1, 0, 1].

Then the frequency map after iterating the first array looks like {0=2, 1=1}, and after counting the first 1 in array2, the frequency is decreased to 0, the key 1 is removed from the map, and therefore map.containsKey(1) is false and the subsequent occurrences of 1 in array2 are excluded from the intersection.


Actually removal from the map may be skipped, if the remaining frequency is just compared to 0 as shown below.

Also, regarding the implementation: using method Map::merge may help to make the method more concise:

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();
}
  •  Tags:  
  • java
  • Related