简体   繁体   中英

Find complementary pairs in array in Java

I am attempting to find how many pairs of values in a given array of integers sum to a specified value k. The logic works if the list contains duplicate values, provided each value has only one complement in the list to sum to k. The issue is that if multiple complements to a given value exist in the list, only one match is counted.

What I have attempted so far is as follows:

  int numberOfWays(int[] arr, int k) {
    // Write your code here
    int output = 0;
    HashMap<Integer, Integer> map = new HashMap();
    for(int i = 0; i < arr.length; i++) {
      int complement = k - arr[i];
      if(map.containsKey(complement)) {
        output++;
      }
      map.put(arr[i],i);
      System.out.println(map);
    }
    return output;
  }

This works for a case as such: k = 6, arr = [1, 2, 3, 4, 3] However, it doesn't work when there are more than two duplicates: k = 6, arr = [1, 5, 3, 3, 3]

For the case that doesn't work the expected result is 4 but the actual is 3.

I can't seem to figure out why that's the case. Any ideas?

The reason it didn't work for the second one is, 3 should match 2 other 3s. But map only supports one. The change should be:


 int numberOfWays(int[] arr, int k) {
    // Write your code here
    int output = 0;
    HashMap<Integer, Integer> map = new HashMap();
    for(int i = 0; i < arr.length; i++) {
      int complement = k - arr[i];
      int count = map.getOrDefault(arr[i], 0);
      if(map.containsKey(complement)) {
        count = map.get(complement);
        output = output + count; // 2 3s, should match twice.
      }
      map.put(arr[i], count + 1);
      System.out.println(map);
    }
    return output;
  }

Another solution. It works on three principles.

  • do a frequency count of the supplied array.
  • for values of k that are even, and arr[i] == k/2 the count is (v(v-1)/2 where v
    is the value for that key. So if k = 8 and the array contains four 4's , then the count, v would be 4 and the sum combinations would be 6 .
  • for values that don't meet the above, the count is the product of the two summands freqencies. So if k = 8 and there are three 3's and two 5's the combinations would be three x two == 6 .
  • the total count is the sum of all the above computations for each pair of summands that add to k
static int numberOfWays(int[] arr, int k) {
    int count = 0;
    Map<Integer, Integer> map = new HashMap<>();
    // accumulate a frequency count values
    for (int i = 0; i < arr.length; i++) {
        map.compute(arr[i], (key, val) -> val == null ? 1 : val + 1);
    }
    System.out.println(map);
    // copy keys to list for iteration to avoid
    // concurrent mod exception when removing keys from
    // map.  This works better than using an iterator.
    List<Integer> keys = new ArrayList<>(map.keySet());
    for (int key : keys) {
        if ((k&1) == 0 && map.containsKey(key) &&  key == k/2) {
            int v = map.get(key) - 1;
            count = count + ((v * (v + 1)) / 2);
        } else if (map.containsKey(k-key)) {
            System.out.println("trying");
            count += (map.get(key) * map.get(k - key));
        }

        map.remove(key);
    }
    return count;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM