Max absolute sum in a array - java

I am came across this question recently but didn't get any idea about solving this. Can you some one help with pseudo code.
Given an array with four integers A, B, C, D, shuffle them in some order. If the integers are unique then there are 24 shuffles. My task is get the best shuffle such that
F(S) = abs(s[0]-s[1]) + abs(s[1]-s[2])+ abs(s[2]-s[3])
is maximum
For example consider this example
A=5, B= 3, C=-1, D =5
s[0]=5, s[1]=-1, s[2]= 5, s[3] =3
will give me maximum sum which is
F[s] =14
The time and space complexity are O(1).

Since your array has a bounded size, any algorithm you use that terminates will have time and space complexity O(1). Therefore, the simple algorithm of "try all permutations and find the best one" will solve the problem in the appropriate time bounds. I don't mean to say that this is by any stretch of the imagination the ideal algorithm, but if all you need is something that works in time/space O(1), then you've got your answer.
Hope this helps!

Algorithm
Consider laying out your points in sorted order:
A B C D
Let x be the distance AB
Let y be the distance BC
Let z be the distance CD
An order which will always give the best score is BDAC with score 2x+3y+2z.
Example
In your example, the sorted points are:
A=-1 B= 3 C=5 D=5
x=4, y=2, z=0
So the best order will be BDAC=3->5->-1->5 with score 14.
Hints towards Proof
You can prove this result be simply considering all permutations of the path between the 4 points, and computing the score in terms of x,y,z.
e.g.
ABCD -> x+y+z
ACBD -> x+3y+z
ADBC -> x+3y+2z
etc.
In any permutation, the score will use x at most twice (because A is on the end so the route can only go to or from A twice). Similarly, z is used at most twice because D is on the end. y can be used at most three times because there are three things being added.
The permutation BDAC uses x twice, z twice, and y three times so can never be beaten.

If array is sorted this solution also works:
F(S)= 2*abs(s[0]-s[3]) + abs(s[1]-s[2])
where s[0]=A, s[1]=B, s[2]=C and s[3]=D.

Related

How to solve the closest subset sum problem in Java for 100+ element arrays?

I have came across a subset sum problem recently. I was able to solve it for smaller arrays using Java earlier, but in this case I have really no idea what should I do. Brute force and recurrence is probably not an option, as I came across out of memory problem.
So, let's say we have an array of {2500, 3200, 3300}. We are looking for the sum closest to the desired number K = 135000. The main difference is that we can use numbers from the array multiple times.
Ok, if we can use them multiple times, then we can change it to more "traditional" way - just divide K by each of these numbers - that is 54, 42 and 40 - and create a new array, which has those numbers the number of times received from dividing. It would be {2500, 2500, 2500, ... , ... 3300, 3300} and the new array would have the length of 136. Now this is much more than 3.
So - how to solve the closest subset sum problem, where we can pick more than 2 numbers from the array of 136 elements or more using Java?
The thing I want to get is not only the closest sum, but also a list of elements which gave that sum.
I heard and was reading about dynamic programing, approximation algorithms and genetic algorithms, but unfortunately I have no idea about those. I did genetic algorithm for a different case some time ago, but I am not sure how to use it in this case.
Any ideas? I will be really glad for help.
I am not going to solve it for you. but I'll give you the key ideas in pseudocode (aka Python).
We start with a state that represents the following statement: "I don't know how to arrive to any numbers. The best thing I can generate is 0. I have not yet processed the fact that I could get to 0."
In data:
can_generate = set()
todo = [0]
best = 0
K = 135000
What we will do is, while anything is in todo, take off a value, see if it is new to us. If it is, we might update best, and possibly add new values to todo. Like this:
while len(todo):
value = todo.pop()
if value not in can_generate:
can_generate.add(value)
if abs(K-value) < abs(K-best):
best = value
if value < K:
for term in [2500, 3200, 3300]:
todo.append(value + term)
Now that we know the values in can_generate, we search backwards to find how to get there.
answer = []
while 0 < best:
for term in [3300, 3200, 2500]:
if best - term in can_generate:
answer.append(term)
best -= term
break

How to get the maximum distance of all subsets in an array

I had an interview question as below:
Suppose we have a line and M points in this line. If we define the distance of a subset of points which has N (N <= M) points to be the minimum distance of the distance between of each pair of point, write a algorithm to find the maximum distance of all subsets, each one has N points...
By this I mean, if we have an array {1,2,10}, and N=2, then the subset with the maximum distance should be {1,10}. My first thought was to get all the combinations of subset and calculate the distance of each one, but the interviewer didn't like it because it would take too much time. Does anyone have a time efficient idea?
You need to sort the array, and find the 1st element(Smallest) and M will always be the last element (largest), So subset will always be the {smallest,Largest}.
Having things arranged along a line is often a tip-off that dynamic programming will work.
Work from left to right. At each point in the line work out, for k = 1..N the set of points of size k amongst those seen so far that has the largest minimum distance. You can work out the the answers for one point in the line from the answers you have already worked out for points to its left. To find the answer for k points, consider each point to its left and find min(minimum distance for k-1 points at that point, distance from current point to that point). Then take the maximum of these possible values.

Finding A, B such that A + B = M?

I have generated two arrays of random integers, X and Y, both of length n, and my goal is to find integer a in X and integer b in Y such that a + b = m, where m is given by the user. This is not a difficult problem to solve, except for my time constraint being O(n*log n) explicitly, that is, not O(n^2) and not O(n).
I realize both merge sort and quick sort (among others) are of this time complexity, but I cannot figure out how to implement them for this specific situation, because there are multiple arrays involved.
Other information that might be helpful: n is not to be immense, probably less than 50. The values within the arrays are all randomized from 1 to 100 and are not pre-sorted, though I could sort them if need be.

Finding smallest delta available for permutations of a set of numbers

Presume we have a set of 12 objects, lets say {1,2,3,4,5,6,7,8,9,10,11,12}. We must break this set into 4 smaller ones composed of three objects, so that the largest sum and smallest sum of these four sets is minimized. We must find this difference. In our example, {1,7,12},(3,8,9},{4,5,10},{2,6,11}. These four sets satisfy the problem since their sums are 20 and 19, meaning a delta of 1, our answer.
How can one solve this problem for any arbitrary 12 values?
I've tried enumerating all partitions of said set into 4 sets of 3, and finding one with the optimal score. However, time is of the essence, and so I was wondering how one would approach this problem in Java
I don't have exact code on me right now, but what it essentially was was 9 nested for loops, where the first three that nest are one set, the next three are the next set, the last three are another set, and the three left overs are another set. I used a 2D array so that values would be in score[i][0] and score[i][1] would act as an indicator to let me know if that value in score[i][0] had already been placed into a set.
This of course gets tedious and inefficient.
You could easily simplify the problem by finding the values that the sums must approach for a better optimisation :
For instance, in your simple case (1,2...12), then the total sum of every terms is 78. Thus, Each groups must have a sum very close to 78/4=19.
So, let's try a very simple algorithm :
- compute TOTAL_SUM = SUM(terms)
- compute TARGET_SUM = TOTAL_SUM / number(terms)
- set DELTA=0
- loop {
- Try to split terms in groups where TARGET_SUM - DELTA <= SUM <= TARGET_SUM + DELTA
- if a solution is found, exit
- DELTA = DELTA + 1
- }
Ok, I did not helped you much with this "Try to split..." step. But it should look like you own solution, except that you have additional constraints which can help you to speed up the process.
Hope this helps.

Algorithm which tells if a number is obtainable from a given set using only '+' ,'*' and brackets

I have two list of numbers, for every member of the second one I must tell if it's obtainable using all the numbers of the first one and placing '+' or '*' and as many '(' ')' I want.
I can't change the order .
List1 can contain a max of 20 elements beetween 1 and 100.
List2 can contain max 5 elements beetween 1 and 20'000.
EX:
List1=[2 4 3 5]
List2=[19 15 24]
19-> 2+(4*3)+5 YES
15 NO
24->2*(4+3+5) YES
With brute force it takes ages to handle inputs with List1 larger than 10.
edit: numbers are always positive.
edit:
I find the max and min numbers that are obtainable from the list and then I discard all the possibilities that have the target outside this range, then I try all the remaining ones.
MAX=n1*n2*n3*....*ni if there are 1 thei r added to their smallest neighbour
MIN=n1+n2+....+ni 1 excluded
Still it's not fast enough when input are big (List1 longer than 10 or numbers in List2 bigger than 10000)
For each sublist of List1, compute the numbers between 1 and 20,000 that can be made with that sublist. The resulting DP bears resemblance to CYK.
I'm being somewhat vague here because this is almost certainly a programming contest problem.
#u mad is correct, but I'll give a little more detail.
Suppose that n = size of list 1. For each 0 <= i < j < n you need to compute all of the distinct values in the range (1..20_000) that can be made from the numbers in the interval [i, j-1]. You can do this with recursion and memoization.
Once you've done this then the problem is easy.
You could try a smart brute force which discards sets of equations by chunks.

Categories