Combination

def combination(arr):
    '''
    input: [a, b, c]
    output: [[]
            [a], [b], [c]
            [a, b], [a, c], [b, c]
            [a, b, c]]
    note: the order of the output does not matter.
    '''
    if not arr:
        return arr

    result = [[]]
    buff = []
    combination_helper(arr, 0, buff, result)
    return result

def combination_helper(arr, index, buff, result):
    # base case
    if index >= len(arr):
        return

    for i in xrange(index, len(arr)):
        buff.append(arr[i])
        result.append(list(buff))

        # recursion
        combination_helper(arr, i + 1, buff, result)

        buff.pop()

def combination_without_duplicates(arr):
    '''
    input: [a, b, c, c]
    output: [[]
            [a], [b], [c]
            [a, b], [a, c], [b, c], [c, c]
            [a, b, c], [a, c, c], [b, c, c]
            [a, b, c, c]]
    note: the order of the output does not matter.
          do not allow the duplicates in result.
    '''
    if not arr:
        return arr

    result = [[]]
    result_set = set([''])
    buff = []
    combination_without_duplicates_helper(arr, 0, buff, result, result_set)
    return result

def combination_without_duplicates_helper(arr, index, buff, result, result_set):
    # base
    if index >= len(arr):
        return

    for i in xrange(index, len(arr)):
        buff.append(arr[i])
        buff_str = ','.join(buff)
        if buff_str not in result_set:
            result_set.add(buff_str)
            result.append(list(buff))

            # recursion
            ## The reason why I do not put the 'recursion' outside of the 'if' statement is that
            ## if the set has cached the buff, which means this combination or part of combination
            ## has been processed, there is no need to do 'recursion' again. 
            combination_without_duplicates_helper(arr, i + 1, buff, result, result_set)

        buff.pop()

if __name__ == '__main__':
    arr_1 = ['a', 'b', 'c']
    result_1 = combination(arr_1)
    print result_1

    arr_2 = ['a', 'b', 'c', 'c']
    result_2 = combination_without_duplicates(arr_2)
    print result_2

Note:

  • The time complexity = O(n!), n is the number of the elements in the given array.

  • The space complexity = O\(n!\), n is the number of the elements in the given array.

  • O(n!) > O(2 power of n), O(n!) is less efficient than O(2 power of n)

Combination formula

http://www.mathwords.com/c/combination\_formula.htm

'n choose r': The number of possible combinations from n choose r

Note: '阶乘' => 'Factorial'

       n! = n \* \(n - 1\) \* \(n - 2\) \* \(n - 3\) \* ... ... \* 1

For example:

n = 3, r = 2, the given set = ['a', 'b', 'c'], the number of possible combinations choosing 2 elements from the given set is 3

input: ['a', 'b', 'c']

output: ['a', 'b'], ['a', 'c'], ['b', 'c']

results matching ""

    No results matching ""