FAST unique combinations (from list with duplicates) WITHOUT LOOKUPS

前端 未结 2 1552
迷失自我
迷失自我 2020-12-16 02:09

I seems that in spite of the fact that there are online plenty of algorithms and functions for generating unique combinations of any size from a list of unique items, there

2条回答
  •  感情败类
    2020-12-16 02:46

    Instead of post-processing/filtering your output, you can pre-process your input list. This way, you can avoid generating duplicates in the first place. Pre-processing involves either sorting (or using a collections.Counter on) the input. One possible recursive realization is:

    def subbags(bag, k):
        a = sorted(bag)
        n = len(a)
        sub = []
    
        def index_of_next_unique_item(i):
            j = i + 1
    
            while j < n and a[j] == a[i]:
                j += 1
    
            return j
    
        def combinate(i):
            if len(sub) == k:
                yield tuple(sub)
            elif n - i >= k - len(sub):
                sub.append(a[i])
                yield from combinate(i + 1)
                sub.pop()
                yield from combinate(index_of_next_unique_item(i))
    
        yield from combinate(0)
    
    bag = [1, 2, 3, 1, 2, 1]
    k = 3
    i = -1
    
    print(sorted(bag), k)
    print('---')
    
    for i, subbag in enumerate(subbags(bag, k)):
        print(subbag)
    
    print('---')
    print(i + 1)
    

    Output:

    [1, 1, 1, 2, 2, 3] 3
    ---
    (1, 1, 1)
    (1, 1, 2)
    (1, 1, 3)
    (1, 2, 2)
    (1, 2, 3)
    (2, 2, 3)
    ---
    6
    

    Requires some stack space for the recursion, but this + sorting the input should use substantially less time + memory than generating and discarding repeats.

提交回复
热议问题