-1

Given a bunch of integer numbers, please output all combination of all possible numbers by using plus operation only.

For example,

[10, 20] => [10, 20, 30]
[1, 2, 3] => [1, 2, 3, 4, 5, 6]
[10, 20, 20, 50] => [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

Could someone help me with a method to do that in Java ?

I have made tries and I think it works, but looking for other solutions.

public int[] getCoins2(int[] coins) {
    Set<Integer> result = new TreeSet<>();

    for (int coin : coins) {
        result.addAll(result.stream().map(value -> value + coin).collect(Collectors.toSet()));
        result.add(coin);
    }

    return toInt(result);
}

public int[] toInt(Set<Integer> set) {
    int[] a = new int[set.size()];

    int i = 0;

    for (Integer val : set) {
        a[i++] = val;
    }

    return a;
}

public static void main(String[] args) {

    CoinCombination combination = new CoinCombination();
    int[] coins = {10, 20, 20, 50, 100};

    System.out.println(Arrays.toString(combination.getCoins2(coins)));
}
sendon1982
  • 9,982
  • 61
  • 44
  • 2
    OP, has your account been hacked or something? It appears you have been a member for 5 years, I think you know how SO works? – Scary Wombat Nov 21 '18 at 05:39
  • Hint: start with a bubble sort algorithm, but don't actually sort the list. Rather put the sum of elements into a hashset – OneCricketeer Nov 21 '18 at 05:39
  • What do you mean you "think it works"? Do you have unit tests? – OneCricketeer Nov 21 '18 at 05:42
  • I do not know how OP works. I have not posted any question for long time – sendon1982 Nov 21 '18 at 05:42
  • I had unit test, but i cannot cover all the cases – sendon1982 Nov 21 '18 at 05:42
  • Okay, then show the ones that fail, and the output you're getting... Also, stepping through with a debugger would help – OneCricketeer Nov 21 '18 at 05:43
  • It does not matter if the source array is sorted or not, it will not impact result – sendon1982 Nov 21 '18 at 05:44
  • I do not have the one failed, I mean all my test cases passed from size one array to size 5 array – sendon1982 Nov 21 '18 at 05:44
  • I specifically said not to sort the list, rather I implied to start with a nested for loop over the values – OneCricketeer Nov 21 '18 at 05:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184004/discussion-between-cricket-007-and-sendon1982). – OneCricketeer Nov 21 '18 at 05:45
  • 1
    “Looking for other solutions” is not a very good question – Joakim Danielson Nov 21 '18 at 06:22
  • Related: [Return all possible sums that can be formed by using numbers in array JAVA](https://stackoverflow.com/questions/34965270/return-all-possible-sums-that-can-be-formed-by-using-numbers-in-array-java). Search for more. – Ole V.V. Nov 21 '18 at 06:35
  • 1
    I’d go for a recursive method for generating the combinations and a `TreeSet` for storing the results for sorted output. – Ole V.V. Nov 21 '18 at 06:36
  • When you say all possible sums, do you mean subsequence sums as well? – nice_dev Nov 21 '18 at 07:18
  • If you have 5 numbers in your array, then each number can be included, or not included in the sum. That maps neatly to 5 binary bits. Generate all the binary numbers from b00000 to b11111. Calculate the sums of all numbers which are flagged with a 1. Remove duplicate results and you have solved the problem. – rossum Nov 21 '18 at 20:35
  • @vivek_23 yes, you can use only one number or two or all to sum up to have a new result. – sendon1982 Nov 21 '18 at 22:27
  • @OleV.V. Thanks, i checked it, but i found out it is hard to understand recursion version for me :( – sendon1982 Nov 21 '18 at 22:34
  • Assuming your iterative code is doing the job, you don’t need to bother. Recursion is hard to understand at first, a great tool once you master it (at long last). – Ole V.V. Nov 21 '18 at 22:49
  • OK, i will keep to study more about recurssion – sendon1982 Nov 22 '18 at 02:56

1 Answers1

1

As you mentioned in your problem statement:

please output all combination of all possible numbers by using plus operation only.

  • The time complexity of the solution is going to remain exponential, that is, O(2N-1), since we have to try every subsequence of the array.

  • Since you are using a TreeSet, the complexity of add will add a overhead of log(n) and addAll() would add a complexity of O(m log (n)) in the worst case, where m and n are the number of elements in each tree. See this answer.

  • Technically speaking, this would add up the O(m log(n)) complexity at each step making it O(2N - 1) * O(m log(n)).

  • I suggest you to better use a HashSet where add() and contains() would give you a O(1) performance on average(could go up to O(n) if there are collisions but is usually not the case).

  • This way, complexity remains O(2N-1) with an additional(not multiplicative) overhead of sort at the end(if you wish to have it sorted) which would be O(m log m) where m ~ 2N - 1. You can compare run time of both approaches too.

Code:

import java.util.*;
public class CoinCombination {
        public List<Integer> getCoinSums(int[] coins) {
        Set<Integer> set = new HashSet<>();
        List<Integer> sums = new ArrayList<>();
        for (int coin : coins) {
            int size = sums.size(); 
            for(int j=0;j<size;++j){
                int new_sum = sums.get(j) + coin;
                if(!set.contains(new_sum)){
                    sums.add(new_sum);   
                    set.add(new_sum);
                }
            }
            if(!set.contains(coin)){
                sums.add(coin);
                set.add(coin);
            }
        }

        Collections.sort(sums);
        return sums;
    }

    public static void main(String[] args) {
        CoinCombination combination = new CoinCombination();
        int[][] coins = {
            {10,20},
            {1,2,3},
            {10, 20, 20, 50},
            {10, 20, 20, 50, 100}
        };
        for(int[] each_set_of_coins : coins){
            System.out.println(combination.getCoinSums(each_set_of_coins).toString());
        }        
    }
}

Output:

[10, 20, 30]
[1, 2, 3, 4, 5, 6]
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200]
nice_dev
  • 17,053
  • 2
  • 21
  • 35