4

I have two lists. List L1 contains all positive integers, list L2 contains positive numbers (e.g. 0.01,0.1,0.5,3,5,10,100....).

Given a small positive number M (e.g. 0.10948472), find a,b from L1 and cfrom L2 s.t. (b/a)*c is maximized but still <=M

Note that list L2 is fixed (length around 7000), list L1 has variable length (can have single element or up to 3000 elements).

How can we efficiently design an algorithm to solve this? I'm thinking about using divide and conquer on list L1 to break it into two then combine, but didn't work out. Anyone can solve it efficiently?

Update: Currently I worked out some inefficient but correct solutions: Sort 'L1' first. Divide 'L1' into two chunks: one chunk is the first N-1 elements, another chunk is the last element. Suppose best a,b,c has been found on the first N-1 elements of L1, I check whether we can find some a in first chunk and b in second chunk (one element only) and some c, such that (b/a)*c improves. Since I have to loop through each element in L2, although it's nlogn, still appears to be slow

  • Did you manage to do it in an ineffecient way first? – Tobias Brösamle Feb 13 '19 at 14:33
  • Yes, I worked out two inefficient but correct solutions. Let me have some update on the question, thanks – ADS_Auckland Feb 13 '19 at 14:39
  • 1
    I guess it can be done at `O((n^2) * log(n^2))` by create array of all possible `b/a` and `d/c` and sort them. What complexity you trying to achieve? – dWinder Feb 13 '19 at 14:44
  • @dWinder I'm trying to achieve O(nlogn) at least – ADS_Auckland Feb 13 '19 at 14:45
  • What do you mean with n in O(nlog n)? Technically you have two arrays of different length, call them n1 from length(L1) and n2 for length(L2). I believe you can get O(n1*n2*log(n1)) and since n2 is fixed that is technically O(n*log(n)) - but that seems like cheating. – Hans Olsson Feb 13 '19 at 15:43

3 Answers3

1

This problem is 3SUM-hard, so you're unlikely to do significantly better than Theta(n^2). If I understand correctly, your current algorithm is O(n^2 log n), which doesn't leave a lot of room for improvement.

David Eisenstat
  • 64,237
  • 7
  • 60
  • 120
1

from what i understand, you dont have to loop through each element of L2 for a given a/b combination. sort L2 in ascending order. then suppose you pick the first combination of a/b from L1. for c, you can pick the element in the middle of L2, i.e. at index 3500 and multiply with a/b. if the answer is less than M, you could pick the element at a higher index, for example at 7000*3/4 which is 5250. if answer is still less, go higher still. if instead (a/b)*c exceeds M, pick a lower index. you could converge to the maximized value of c for that particular a/b combination.

P.S. needless to say, after sorting L1 and L2, you could add an if statement to eliminate those elements in L1 or L2 which will always exceed M for any value of L2 or L1 respectively.

Shaheer Bin Arif
  • 222
  • 1
  • 3
  • 11
0

Sort L1 ascending. Let's say |L1| = n. This is O(n log n).

For each element in L2 (the 'c' in the equation), do the following (so O(1) times since L2 is fixed).

1. For the first element in L1 (which we'll treat as the 'a' in the equation), use binary search on L1 to find a second element (the 'b') s.t. (b/a)*c is maximized but still <=M.
2. Now, we'll move on to the next element in L1. Note that we're increasing the denominator, so the numerator will either stay the same or increase. We'll just iterate rather than using binary search.
3. repeat step 2.

In steps 2 and 3 we keep track of the best values we've found so far for a, b, and c.

Running time: O(n log n) to sort, then in step 2 we only ever increment the numerator or denominator once from each value, so this is O(n) + O(n) = O(n).

This takes advantage of L2 being fixed. If |L2|=m and m isn't fixed then this would take O(n log n) + O(m*n)

Dave
  • 7,460
  • 3
  • 26
  • 39
  • Hi Dave, thanks for the suggestion. In step 2 'numerator will either stay the same or increase': it means we will move from the current position one step at a time to the right until we find the maximized value, correct? – ADS_Auckland Feb 15 '19 at 13:09
  • @ADS_Auckland yep! – Dave Feb 15 '19 at 16:38