add elements of array thats sum equals the largest element - ruby

what is a way to add elements of array thats sum would equal the largest element in the array?
example for this array [4, 6, 23, 10, 1, 3] I have sorted the array first resulting in [1, 3, 4, 6, 10, 23] then I pop the last digit or the last element max = 23. I'm left with [1, 3, 4, 6, 10] and need a way to find a way to find the elements that add up to 23 which are 3 + 4 + 6 + 10 = 23. The elements don't have to be subsequent they can be at random points of the array but they must add up to max.
I can find the permutations of the sorted array from 2 elements to n-1 elements and sum them and compare them to max but that seems inefficient. plz help

This is exactly the subset sum problem, which is NP-Complete, but if your numbers are relatively small integers, there is an efficient pseudo-polynomial solution using Dynamic Programming:
D(i,0) = TRUE
D(0,x) = FALSE x>0
D(i,x) = D(i-1,x) OR D(i-1,x-arr[i])
If there is a solution, you need to step back in the matrix created by the DP solution, and "record" each choice you have made along the way, to get the elements used for the summation. This thread deals with how to find the actual elements in a very similar problem (known as knapsack problem), which is solved similarly: How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?

Related

How to find minimum pairing cost? (Any Language)

I came across an algorithm question recently and I still haven't been able to come up with a way to solve it. Can anyone help with pseudocode or logic?
Here is the question:
There are n elements in the array. N is an odd number. When we exclude 1 element from array, we are finding the minimum pairing cost.
Rules:
1 <= n <= 1001
n % 2 = 1
Example:
Given array is [4, 2, 1, 7, 8]
When we pair items with the closest ones [[1,2], [7,8]] and "4" is excluded.
So the minimum cost is |1 - 2| + |7 - 8| = 2;
What i tried:
Sort array first: [1,2,4,7,8]
Remove the middle element: 4
Pair items with the next ones: [[1, 2], [7, 8]]
According the example it works but what if the given array is [1, 7, 8, 16, 17]?
Sort array first: [1, 7, 8, 16, 17]
Remove the middle element: 8
Pair items with the next ones: [[1, 7], [16, 17]] Wrong Answer
"1" must be excluded and the pairs must be [[7, 8], [16, 17]]
Once the array is sorted, you can pair all elements from left to right, keep track of the total sum, and replace the last pairing with one starting from the right, updating the total sum if it's smaller.
In pseudo-code (all zero-based indexing):
let S be the sum of all pairing costs of
elements 2i and 2i+1 for i from 0 to (n-3)/2
(that is all pairings when you exclude the very last element)
let j = (n-1)/2
for i from (n-3)/2 to 0 (included):
let L be the pairing cost of elements 2i and 2i+1
let R be the pairing cost of elements 2i+1 and 2i+2
let S' = S - L + R
if S' < S
replace S with S'
replace j with i
2j is the element to exclude
Sorting the array first is a good start. Once you've done that, you have a choice of removing any value from index 1..N. A brute-force approach would be to calculate the pairing cost of omitting index 1, then recalculate omitting only index 2, and so on until you reach index N.
You'd be calculating many of the pairs over and over. To avoid that, consider that all the pairs to the left of your omitted index are paired odd-even (from the perspective of starting at element 1) and to the right of the omitted index will be even-odd. If you precalculate the sums of the left pairings and the sums of the right pairings into two arrays, you could determine the minimum cost at each position as the minimum sum of both values at each position of those two arrays.

Maximum Sum for Subarray with fixed cutoff

I have a list of integers, and I need to find a way to get the maximum sum of a subset of them, adding elements to the total until the sum is equal to (or greater than) a fixed cutoff. I know this seems similar to the knapsack, but I was unsure whether it was equivalent.
Sorting the array and adding the maximum element until sum <= cutoff does not work. Observe the following list:
list = [6, 5, 4, 4, 4, 3, 2, 2, 1]
cutoff = 15
For this list, doing it the naive way results in a sum of 15, which is very sub-optimal. As far as I can see, the maximum you could arrive at using this list is 20, by adding 4 + 4 + 4 + 2 + 6. If this is just a different version of knapsack, I can just implement a knapsack solution, as I probably have small enough lists to get away with this, but I'd prefer to do something more efficient.
First of all in any sum, you won't have produced a worse result by adding the largest element last. So there is no harm in assuming that the elements are sorted from smallest to largest as a first step.
And now you use a dynamic programming approach similar to the usual subset sum.
def best_cutoff_sum (cutoff, elements):
elements = sorted(elements)
sums = {0: None}
for e in elements:
next_sums = {}
for v, path in sums.iteritems():
next_sums[v] = path
if v < cutoff:
next_sums[v + e] = [e, path]
sums = next_sums
best = max(sums.keys())
return (best, sums[best])
print(best_cutoff_sum(15, [6, 5, 4, 4, 4, 3, 2, 2, 1]))
With a little work you can turn the path from the nested array it currently is to whatever format you want.
If your list of non-negative elements has n elements, your cutoff is c and your maximum value is v, then this algorithm will take time O(n * (k + v))

Find the maximum weight that can be collected from a store under given limit

I faced this problem in placement exam of SAP labs:
It's your birthday, so you are given a bag with a fixed space 'S'. You can go to a store and pick as many items you like which can be accommodated inside your bag. The store has 'n' items and each item occupies a space s[i]. You have to find out the maximum space in bag which you can fill.
For example, say the limit of you bag is S = 15 and the store has 10 items of sizes [1, 7, 3, 5, 4, 10, 6, 15, 20, 8]. Now you can fill 15 space by various ways such as [1, 7, 3, 4], [7, 3, 5], [15], [5, 10] and many more. So you return 15.
Note: There is quirk in the sizes of items. All of the items but at most 15 follow the following rule: *for all i, j, either size[i]>=2*size[j]+1 or size[j] >= 2*size[i] +1 if i ≠ j.*
Constraints:
1<= n <= 60.
1<= size[i] <= 10^17.
1<= S <= 10^18.
Example: S = 9, n = 5, sizes = [1, 7, 4, 4, 10].
Output: 8. You can't fill exactly 9 space in any way. You can fill 8 space either by using [1, 7] or [4, 4].
Let´s call x the elements that follow that rule. Note that for this set of elements, we have some nice properties:
Given x in sorted ascending order, sum(x[i..j]) < x[j + 1]
To solve maximum sum <= k, just iterate in sorted descending order and substract from k x[i] whenever possible. original k - remaining k is the solution. Assuming elements were already sorted, this is O(|x|).
One way to obtain this set is to iterate items sorted by size in ascending order and add to set if :
set has no elements or
current element >= 2 * size[lastElementAdded] + 1
Now we are left with at most 15 items that do not follow this rule. So we can´t use the efficient solving like before. For each item, we can consider to put it or not in the bag. This leads to 2^15 possible sums. For each of those sums, we can run our method for the elements that follow the rule.
Overall complexity: 2^15 * (n - 15). For n = 60, this should be solved in less than a second.
As an exercise: by using accumulated sums and binary search, it can be brought down to 2^15 * log2(n - 15).

Find 2 subarrays from an array of n elements that have equal or close to sum of their elements

Let's say you have an array = [2, 3, 3, 6, 7], it is not sorted, but you can sort it if you would like. Find 2 subarrays using all the elements in the array so that the resulting subarrays will be [2, 3, 6] and [7, 3] since 2 + 3 + 6 = 11 and 7 + 3 = 10.
The sums of the resulting subarrays don't have to be equal but they should be as close as they can be.
My first approach was sorting this elements in desc order and taking elements from each end of the array.
Any help will be appreciate it, thanks.
Suppose the sum of all the numbers is N. To determine whether there is a solution where the two subsets have equal sum is equivalent to the problem of determining whether there is a subset that adds to N / 2.
The best known algorithms for this problem are exponential.
I've found out that this is a well-known problem known as the partition problem. For more information: https://en.wikipedia.org/wiki/Partition_problem

Algorithm for sorting an 2D array

Given a 2 dimensional array (a matrix) with n rows and n columns, with it's rows and columns sorted, what would be the efficient algorithm to sort it?
For example:
Input
1 5 8
3 6 9
8 12 15
Output:
1 3 5 6 8 8 9 12 14 15
I want a pseudo code that solve problem in best time.
The first idea that comes to my mind is to generalize the "Merge Two Sorted Arrays" algorithm.
Maintain n pointers, each pointer for a row in your 2D array.
Each iteration compare all the pointers and pick the minimum value.
Push the minimum value to the result array.
Advance the pointer for that minimum value row.
Make sure you don't compare pointers beyond the row length.
This will be an O(n^2) algorithm.
Also take a look at this solution here: http://www.geeksforgeeks.org/merge-k-sorted-arrays/
Update: 06:30 UTC
Also one other idea that came to my mind is to merge each two rows separately, and recursively repeat the process, this will be an O(n.log(n)) algorithm.
I believe it shouldn't take more than O(n log(n)) under any circumstance since this is what we get for quick sort without considering the sorted rows and columns.
probably you would get a good answer using merge function in merge sort. call it recursively. but again it would give you O(n log(n)). although when it reaches size of sqrt(n) it will return instead of going all the way to problem with size 1. but still log( n sqrt(n) ) has the same order of growth as n log(n) but in real problem this would probably give you a better result.
EDIT:
I assumed we merge rows or columns (doesn't make any difference).
Change fast sort algorithm to access your 2d array as 1d. Like this:
before:
sort(array){
...
for(i = 0; i<array.length; i++){
if(array[i]){
...
}
after:
sort(array){
...
for(i = 0; i < M * N; i++){
if(array[i/N][i%N]){
...
}
Please edit your question as to what language you are looking in to?
In python:
>>> x = [[1, 5, 8, 10],
[3, 4, 5, 6],
[2, 3, 3, 9]]
>>> x = sorted([items for sub in x for items in sub])
>>> print x
[1, 2, 3, 3, 3, 4, 5, 5, 6, 8, 9, 10]
Pseudo-code
Create an empty list
Loop over the matrix,
get the smallest value,
append it to the empty list,
and remove that value from the matrix.

Resources