What technique do I use for when I want to check all possible combinations of a set?

后端 未结 9 2054
既然无缘
既然无缘 2021-01-18 23:38

I\'m working through an interview question that goes like:

Given an array of integers and sum, check whether any combination adds up to the sum.

相关标签:
9条回答
  • 2021-01-18 23:51

    If you do choose to calculate a powerset, it can be done quite easily in a functional way.

    In Haskell, there is a subsequences functions which essentially returns the powerset of any set, as a list of lists.

    Or you can write it yourself

    powerSet :: [a] -> [[a]]
    powerSet [] = [[]]
    powerSet x:xs = map (:x) (powerSet xs) ++ (powerSet xs)
    
    0 讨论(0)
  • 2021-01-19 00:02

    That sounds like a classic recursion problem. You start with the first element and consider the rest of the array; for each element, either it is picked or it isn't. The base case is when the start index is greater than the length of the array. Something like

    public static bool canSum(int start, int[] array, int sum)
    {
          if (start >= array.Length)
               return sum == 0;
          return canSum(start + 1, array, sum - array[start]) || canSum(start + 1, array, sum);
    }
    
    0 讨论(0)
  • 2021-01-19 00:04

    This doesn't answer your "combination" question, but it's probably the optimal solution to the Question :P

    This is the subset sum problem problem where you have to search N sums.

    Subset sum has a pseudo polynomial algorithm using dynamic programming:

    psuedocode from this link

    Subset-Sum-Solver[S = w1,w2, . . . ,wn,B]
    1 Initialize M[0..n, 0..B] everywhere False apart from M[0, 0] = True
    2 for i  from 1 to n
      do
    3    for w from  0 to B
         do
    4        M[i,w] = M[i − 1,w] _M[i − 1,w − wi]
             (any reference outside the array returns false)
    5 Output M[n,B]
    

    where B is the sum, S is the set of numbers, n is the cardinality of S (number of elements in S), and M is a n by B matrix . This algorithm is O(nB)

    In the case of the interview question, do this for each sum, and you get an algorithm that's O(nmB) where m is the number of sums that you have to test.

    The question is a little ambiguous, is the array of integers used to get subsets also the same array of sums? i.e. do a subset of integers in array A also add up to one of the integers in array A? in that case, then the algorithm is O(n^2B) since n == m

    0 讨论(0)
  • 2021-01-19 00:04

    I see two options:

    1. Compute the Power Set of the input array and check the sum of each element in the power set (see http://en.wikipedia.org/wiki/Power_set). This is probably O(2^N) and not good for large N
    2. Try something with the 0-1 Knapsack problem (see http://en.wikipedia.org/wiki/Knapsack_problem). This should either find the greatest sum less than your desired value, a sum that is your desired value, or not find anything. Based on the output, you can answer your original question. 0-1 Knapsack is nice because it runs in polynomial time O(N^c) where c is constant. I don't remember if it works for negative numbers though.
    0 讨论(0)
  • 2021-01-19 00:05

    One handy insight is to realize that the binary representation of all numbers from 0 to (2^N)-1 is actually a set of bit masks for the possible combinations out of N distinct items. For instance, for N=3 (3 items) and thus (2^3)-1 = 7:

    0: 000 = none
    1: 001 = third item
    2: 010 = second item
    3: 011 = second and third items
    4: 100 = first item
    5: 101 = first and third items
    6: 110 = first and second items
    7: 111 = all 3 items
    

    This makes it very easy to loop through all possible selections in a set order (so that it's impossible to skip or double-visit any potential selection).

    0 讨论(0)
  • 2021-01-19 00:05

    Some care with terminology is needed here. Combinations is used to refer to picking k items from a set of n items, where the order of the k items does not matter. The related concept of picking k items from a set of n items, where the order of the k items does matter, is referred to as a permutation.

    What you initially talk about, however:

    Given an array of integers and sum, check whether any combination adds up to the sum.

    is a different thing - here there is no fixed k: you are interested in any size subset of the original items.

    The set of all subsets of a set S is called the power-set of S, and there is a very simple formula for the number of members it contains. I will leave that as an exercise - once you have worked it out, it should be relatively obvious how to enumerate through the members of a set's powerset.

    (Hint: the power-set of { 1, 2 } is { {}, { 1 }, { 2 }, { 1, 2 } })

    0 讨论(0)
提交回复
热议问题