用k个部分对整数分区进行排名和取消排名

时间:2019-06-26 21:16:45

标签: algorithm math combinations ranking integer-partition

对于正整数 n k ,让“ n k 分区”排序 k 个不同的正整数的列表,这些正整数加起来为 n ,并让给定 k 的“等级”划分为 n 是按字典顺序在所有这些列表的排序列表中的位置,从0开始。

例如,有两个2个分区,每个分区5个( n = 5, k = 2):[1,4]和[2,3]。由于按字典顺序[1,4]在[2,3]之前,因此[1,4]的等级为0,[2,3]的等级为1。

所以,我希望能够做两件事:

    给出 n k n k 分区,我想查找等级 n k 分区中的一个。
  • 给出 n k 和一个等级,我想找到 n k 分区那个等级。

我可以这样做而不必计算感兴趣的对象之前的所有 n k 个分区吗?

这个问题与其他问题有所不同,因为我们在这里讨论的是整数分区,而不仅仅是组合。

1 个答案:

答案 0 :(得分:3)

这是Python中的一个解决方案,它依赖于两个想法。首先,进行动态编程以对分区进行计数而不生成分区。其次,如果第一个值为i,那么我们可以将其视为一个i * k框,其中将n-i*k划分为k-1个片段,放在上面。

partition_cache = {}
def distinct_partition_count (n, k):
    if n < k:
        return 0
    elif n < 1:
        return 0
    elif k < 1:
        return 0
    elif k == 1:
        return 1
    elif (n, k) not in partition_cache:
        answer = 0
        for i in range(1, n/k + 1):
            answer = answer + distinct_partition_count(n - i*k, k-1)
        partition_cache[(n, k)] = answer
    return partition_cache[(n, k)]

def rank_distinct_partition (values):
    values2 = sorted(values)
    n = sum(values)
    k = len(values)
    answer = 0
    highwater = 0
    for v in values:
        rise = v - highwater
        for i in range(1, rise):
            answer = answer + distinct_partition_count(n - k*i, k-1)
        highwater = v
        n = n - rise
        k = k - 1
    return answer

def find_ranked_distinct_partition (n, k, rank):
    if k == 1 and rank == 0:
        return [n]
    elif distinct_partition_count(n, k) <= rank:
        return None
    elif rank < 0:
        return None
    else:
        i = 1
        while distinct_partition_count(n - i*k, k-1) <= rank:
            rank = rank - distinct_partition_count(n - i*k, k-1);
            i = i + 1
        answer = find_ranked_distinct_partition(n - i*k, k-1, rank)
        return [i] + [j + i for j in answer]

print(rank_distinct_partition([2, 3])
print(find_ranked_distinct_partition(5, 2, 1))