How to generate all possible combinations with a given condition to make it more efficient?

后端 未结 2 1109
死守一世寂寞
死守一世寂寞 2021-01-18 05:33

(Python) I would like to generate all possible combinations with length 9 out of a sorted list list with 150 numbers. However, that\'s not very efficient, so I want to have

2条回答
  •  一个人的身影
    2021-01-18 06:24

    Here's a solution using a recursive generator function: the function combinations_max_diff takes a list of numbers nums, a number of elements k, and a maximum difference max_diff.

    The helper function does all of the work; it takes a partial combination comb, a number of remaining elements r, a minimum list index i for the next element to be chosen in the combination, and a max_next which controls the maximum size of that next element.

    def combinations_max_diff(nums, k, max_diff):
        # input list must be sorted
        nums = sorted(nums)
        n = len(nums)
    
        def helper(comb, r, i, max_next):
            if r == 0:
                yield comb
            else:
                for ii in range(i, n - r + 1):
                    v = nums[ii]
                    if v > max_next: break
                    comb_v = comb + (v,)
                    yield from helper(comb_v, r - 1, ii + 1, v + max_diff)
    
        return helper((), k, 0, nums[-1])
    

    Example usage:

    >>> nums = [1, 2, 3, 4, 5, 6, 7]
    >>> for c in combinations_max_diff(nums, 3, 2):
    ...     print(c)
    ... 
    (1, 2, 3)
    (1, 2, 4)
    (1, 3, 4)
    (1, 3, 5)
    (2, 3, 4)
    (2, 3, 5)
    (2, 4, 5)
    (2, 4, 6)
    (3, 4, 5)
    (3, 4, 6)
    (3, 5, 6)
    (3, 5, 7)
    (4, 5, 6)
    (4, 5, 7)
    (4, 6, 7)
    (5, 6, 7)
    

    The question asks about efficiency, so here's some idea about that:

    >>> import random, timeit
    >>> nums = sorted(random.randrange(0, 5000) for _ in range(150))
    >>> len(list(combinations_max_diff(nums, 9, 150)))
    16932905
    >>> timeit.timeit(lambda: list(combinations_max_diff(nums, 9, 150)), number=1)
    15.906288493999455
    

    So, about 16 seconds to generate about 17 million combinations, or a little under one microsecond per combination on my machine.

提交回复
热议问题