0

So I'm working on this project and it has me stumped.

We're given 2 arrays of integers. The first array is the set of items we will use and the second array is a set of target values.

From the first array, I am supposed to find if there are any 3 numbers that sum up to one of the target values in the second array. So for every target value in the second array, I check to see if there are any 3 numbers that sum up to that target. If there is, I just print out a "yes" or a "no"

Now, I know how to do this in O(n^3) time, but the project requires O(n^2) and I can't figure out how to do that - largely because I also have to loop through the array of target values and do the check on each of them.

I was given a hint to use graphs, trees, BFS, but even then I'm struggling to see how i can do this.

Anyone know what data structure I should use or how I should approach this? Thank you!


Task: You will write a java program which reads a set of integer data from a file, stores that data into a data structure, and repeatedly determines whether any 3 items from the data set sum to a target value. O(n^2)

Example first array: 15 82 22 36 29 11 31 4 31 Example second array: 119 9 -2 57 29 73 93 Example output: 119 YES 9 NO -2 NO 57 YES 29 NO 73 YES 93 NO

david
  • 1

2 Answers2

0

Not sure if that O(n^2) is supposed to be for each look up, or for the total system. You may want to get clarification on that. That said, here's a potential implementation that is pretty efficient (less than O(n^3) at least, not sure on exact value) if you want to take a look at it. It uses a HashMap so it front loads all the calculations and then makes any following lookups really efficient.

import java.util.Arrays;
import java.util.HashMap;

public class Permutations
{
  public static void main(String[] args)
  {
    int[] array1 = {15, 82, 22, 36, 29, 11, 31, 4, 31};
    int[] array2 = {119, 9, -2, 57, 29, 73, 93};
    
    HashMap<Integer, Integer[]> map = new HashMap<Integer, Integer[]>();
    
    for(int i = 0; i < array1.length; i++)
    {
      for(int j = i + 1; j < array1.length; j++)
      {
        for(int k = j + 1; k < array1.length; k++)
        {
          Integer value = array1[i] + array1[j] + array1[k];
          Integer[] set = {array1[i], array1[j], array1[k]};
          map.put(value, set);
        }
      }
    }
    
    for(int i = 0; i < array2.length; i++)
    {
      if(map.containsKey(array2[i]))
        System.out.print(array2[i] + " YES " + Arrays.toString(map.get(array2[i])));
      else
        System.out.print(array2[i] + " NO");
      
      if(i != array2.length - 1)
        System.out.print(", ");
    }
  }
}
Tim Hunter
  • 826
  • 5
  • 10
  • apologies for that, but yeah it's supposed to be O(n^2) for the total system. Also, a larger hint I recently received was that it should be sorted first and then to use two for loops within one larger for loop (not nested) i.e) for(...){ for(...) {} for(...){} } I believe the outer for loop is for iterating through the target values, while the inner ones are for actually checking if the 3sum exists. – david Oct 05 '20 at 21:38
0

You can store all sums of two integers in a hash map. When you need to find three integers with a given sum, iterate through the array for the first one and ask hash map for the other two. Note that this two integers must be to the right from the first one, so you should store the rightmost position of a sum in the hashmap as value.

import java.util.HashMap;

public class Main {
  public static void main(String[] args) {
    int[] firstArray = {15, 82, 22, 36, 29, 11, 31, 4, 31};
    int[] secondArray = {119, 9, -2, 57, 29, 73, 93};

    HashMap<Integer, Integer> fromPosition = new HashMap<>();
    for (int i = 0; i < firstArray.length; i++) {
      for (int j = i + 1; j < firstArray.length; j++) {
        fromPosition.put(firstArray[i] + firstArray[j], i);
      }
    }

    for (int sum : secondArray) {
      boolean yes = false;
      for (int firstPosition = 0; firstPosition < firstArray.length; firstPosition++) {
        Integer position = fromPosition.get(sum - firstArray[firstPosition]);
        if (position != null && position > firstPosition) {
          yes = true;
          break;
        }
      }
      System.out.println(sum + (yes ? " YES" : " NO"));
    }
  }
}

This takes O(n^2) time and O(n^2) memory (if both arrays have O(n) length).

sharepa
  • 1
  • 2