-1

Assume some arbitrary array of ints, for example [3, 1, 1, 1, 13, 13, 13, 13, 13, 8, 8, 8, 8, 8, 8] (order doesnt matter, I just ordered them so its easier to read)

How can I go about creating a method which, when asked for a range, say [2,4], prints the 2nd most, 3rd most, and 4th most frequent integers in the given array? In this example array, it'd print in order of frequencies: Value: 13. Frequency: 5 Value: 1. Frequency: 3 Value: 3. Frequency: 1

noting how the integer 8 is the most frequent integer, and 3 is the 4th most frequent integer.

0jnats3
  • 85
  • 1
  • 7

2 Answers2

1
public static void main(String[] args) {
    SomeClass obj = new SomeClass();
    obj.printRange(new int[]{2, 4}, new int[]{1, 1, 1, 3, 4, 4, 8, 8});
}

public void printRange(int[] range, int[] arrayOfNumber) {
    // Using HashMap so we can save frequency against each number
    HashMap<Integer, Integer> hashMap = new HashMap<>();
    for (int i = 0; i < arrayOfNumber.length; i++) {
        if (hashMap.get(arrayOfNumber[i]) != null) {
            hashMap.put(arrayOfNumber[i], hashMap.get(arrayOfNumber[i]) + 1);
        } else {
            hashMap.put(arrayOfNumber[i], 1);
        }
    }

    //Sort the hashmap and convert it to linkedhashmap
    LinkedHashMap<Integer, Integer> linkedHashMap = sortHashMapByValues(hashMap);
    Iterator<Map.Entry<Integer, Integer>> itr = linkedHashMap.entrySet().iterator();
    //iterate through the linkedhashmap
    for (int i = 0; i < range[1]; i++) {
        // print only your range: expecting range in array → [2,4]
        // start with range[0]→2, range[1]→4
        if (i >= range[0] && itr.hasNext()) {
            Map.Entry<Integer, Integer> entry = itr.next();
            System.out.println("Range at: " + i);
            System.out.println("key: " + entry.getKey());
            System.out.println("Frequency: " + entry.getValue());
        }
    }
}

public LinkedHashMap<Integer, Integer> sortHashMapByValues(
    HashMap<Integer, Integer> passedMap) {
    List<Integer> mapKeys = new ArrayList<>(passedMap.keySet());
    List<Integer> mapValues = new ArrayList<>(passedMap.values());
    Collections.sort(mapValues);
    Collections.sort(mapKeys);

    LinkedHashMap<Integer, Integer> sortedMap =
        new LinkedHashMap<>();

    Iterator<Integer> valueIt = mapValues.iterator();
    while (valueIt.hasNext()) {
        int val = valueIt.next();
        Iterator<Integer> keyIt = mapKeys.iterator();

        while (keyIt.hasNext()) {
            Integer key = keyIt.next();
            int comp1 = passedMap.get(key);
            int comp2 = val;

            if (comp1 == comp2) {
                keyIt.remove();
                sortedMap.put(key, val);
                break;
            }
        }
    }
    return sortedMap;
}
Vikalp Patel
  • 10,669
  • 6
  • 61
  • 96
1

You want to first fill a map with all integers, where each integer is the key and the frequency is the value. If you encounter an existing integer, you increase the frequency (value).

You then sort the entries in that map by their values (frequencies) and simply put the result into a list.

Now you have a sorted list of entrysets where the key is the integer and the value is the frequency, which you can simply access by index:

public static void main(final String[] args) {
    final int integers[] = new int[] {3, 1, 1, 1, 13, 13, 13, 13, 13, 8, 8, 8, 8, 8, 8};

    final Map<Integer, Integer> integerFrequencies = new HashMap<>();

    // Create a map of all integers with their frequency:
    for (final int i : integers) {
        if (integerFrequencies.containsKey(i)) {
            integerFrequencies.put(i, integerFrequencies.get(i) + 1);
        }
        else {
            integerFrequencies.put(i, 1);
        }
    }

    // Sort the map entries by their value (frequency) into a list:
    final var integerFrequenciesSorted = integerFrequencies.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).collect(Collectors.toList());

    // Print 2nd to 4th entry:
    for (int i = 1; i < 4; i++) {
        final var integerFrequency = integerFrequenciesSorted.get(i);
        System.out.println("Value: " + integerFrequency.getKey() + ". Frequency: " +  integerFrequency.getValue());
    }
}

prints:

Value: 13. Frequency: 5
Value: 1. Frequency: 3
Value: 3. Frequency: 1

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43