当前位置: 首页 > 知识库问答 >
问题:

求整数分区的字典顺序

梅欣然
2023-03-14

对于排列,给定Nk,我有一个函数,可以按字典顺序查找kth排列N。另外,给定一个排列perm,我有一个函数,可以在N的所有排列中找到该排列的词典索引。为此,我使用了这个答案中建议的“阶乘分解”。

现在我想对N的整数分区做同样的事情。例如,对于N=7,我希望能够在索引(左)和分区(右)之间来回:

 0 ( 7 )
 1 ( 6 1 )
 2 ( 5 2 )
 3 ( 5 1 1 )
 4 ( 4 3 )
 5 ( 4 2 1 )
 6 ( 4 1 1 1 )
 7 ( 3 3 1 )
 8 ( 3 2 2 )
 9 ( 3 2 1 1 )
10 ( 3 1 1 1 1 )
11 ( 2 2 2 1 )
12 ( 2 2 1 1 1 )
13 ( 2 1 1 1 1 1 )
14 ( 1 1 1 1 1 1 1 )

我试过一些方法。我想到的最好的是

sum = 0;
for (int i=0; i<length; ++i)
  sum += part[i]*i;
return sum;

其中给出了以下内容:

 0  0( 7 )
 1  1( 6 1 )
 2  2( 5 2 )
 3  3( 5 1 1 )
 3  4( 4 3 )
 4  5( 4 2 1 )
 6  6( 4 1 1 1 )
 5  7( 3 3 1 )
 6  8( 3 2 2 )
 7  9( 3 2 1 1 )
10 10( 3 1 1 1 1 )
 9 11( 2 2 2 1 )
11 12( 2 2 1 1 1 )
15 13( 2 1 1 1 1 1 )
21 14( 1 1 1 1 1 1 1 )

这不太管用,但似乎在正确的轨道上。我之所以想到这一点,是因为它计算了我必须向下移动一个数字的次数(比如6,3,26,3,1,1)。不过,我不知道如何修复它,因为我不知道如何解释何时需要重新组合(比如6,3,1,1转到6,2,2)。

共有2个答案

公冶光亮
2023-03-14
#include <stdio.h>

// number of combinations to divide by the number of k below n
int partition(int n, int k){
    int p,i;

    if(n<0) return 0;
    if(n<2 || k==1) return 1;
    for(p=0,i=1;i<=k;i++){
        p+=partition(n-i,i);
    }
    return p;
}

void part_nth_a(int n, int k, int nth){
    if(n==0)return;
    if(n== 1 || n==k && nth == 0){
        printf("%d ", n);
        return ;
    }
    int i, diff;
    for(i=0;i<k;++i){
        diff = partition(n, k-i) - partition(n, k-i-1);
        if(nth < diff){
            printf("%d ", k-i);
            n -= (k-i);
            if(diff == 1)
                part_nth_a(n, k-i, 0);
            else
                part_nth_a(n, k-i, nth);
            return;
        }
        nth -= diff;
    }
}

void part_nth(int n, int nth){
    if(nth == 0){
        printf("%d ", n);
        return ;
    }
    int i, j, numOfPart;
    for(i=1;i<n;++i){
        numOfPart = n-i < i ? partition(i, n-i) : partition(i, i);
        if(nth <= numOfPart)
            break;
        nth -= numOfPart;
    }
    printf("%d ", n-i);
    if(n-i < i)
        part_nth_a(i, n-i, nth-1);
    else
        part_nth_a(i, i, nth-1);
}

int main(){
    int n = 7;
    int i, numOfPart = partition(n, n);
    for(i=0;i<numOfPart;++i){
        printf("%2d ( ", i);
        part_nth(n, i);
        printf(")\n");
    }
    return 0;
}
李敏学
2023-03-14

想想为什么“阶乘分解”适用于置换,同样的逻辑也适用于这里。但是,不要使用k对于k对象的排列数,必须使用分区函数p(n,k)来计算n的分区数,最大部分为k。对于n=7,这些数字是:

k | p(7,k)
0 | 0
1 | 1
2 | 4
3 | 8
4 | 11
5 | 13
6 | 14
7 | 15

例如,要获得(3,2,1,1)的词典索引,您需要计算

p(3+2+1+1) - [ p(3+2+1+1,3-1) + p(2+1+1,2-1) + p(1+1,1-1) + p(1,1-1) ] - 1

这是15-[410]-1=9。这里你计算的是最大部分小于3的7个分区的数量加上最大部分小于2的4个分区的数量加上。。。同样的逻辑可以扭转这种局面。在C中,是(未经测试的!)功能包括:

int
rank(int part[], int size, int length) {
    int r = 0;
    int n = size;
    int k;
    for (int i=0; i<length; ++i) {
        k = part[i];
        r += numPar(n,k-1);
        n -= k;        
    }
    return numPar(size)-r;
}

int
unrank (int n, int size, int part[]) {
    int N = size;
    n = numPar(N)-n-1;

    int length = 0;

    int k,p;
    while (N>0) {
        for (k=0; k<N; ++k) {
            p = numPar(N,k);
            if (p>n) break;
        }
        parts[length++] = k;
        N -= k;
        n -= numPar(N,k-1);
    }
    return length;
}

这里NumPar(int n)应该返回n的分区数,NumPar(int n, int k)应该返回n的分区数,最多k。您可以使用递归关系自己编写这些。

 类似资料:
  • 整数n的划分是将n写成正整数和的一种方式。对于 例如,对于n=7,一个分区是1 1 5。我需要一个程序来查找所有 使用“r”整数对整数“n”进行分区。例如,

  • 问题内容: 我有一本字典 但是,我需要字典的顺序不同: 做这个的最好方式是什么? 问题答案: 字典 没有顺序 。因此,没有办法做到这一点。 如果您使用的是python2.7 +,则可以使用-在这种情况下,您可以使用检索项目列表,然后将其反向并从反向列表中创建一个新项: 如果您使用的是旧版python,则可以从http://code.activestate.com/recipes/576693/获得

  • 问题内容: 我希望我的字典不区分大小写。 我有以下示例代码: 输出=练习更改颜色 我想要另一个字符串,(以大写字母开头)也给出相同的输出。 我相信有一种使用转换为小写字母的通用方法, 但是我不确定如何将其最好地集成到我的现有代码中。(如果无论如何这将是一种合理,简单的方法)。 问题答案: 如果我对您的理解正确,并且希望以一种不区分大小写的方式键入字典的键,则一种方法是将dict子类化并重载sett

  • 问题内容: 码: 打印。我不确定该方法如何确定l中关键字的顺序。但是,我希望能够以“适当”的顺序检索关键字。当然,正确的顺序将创建列表。 和这个: 问题答案: 你可以使用OrderedDict(需要Python 2.7)或更高版本。 另外,请注意,由于dict你使用进行创建的操作已经忘记了元素的顺序,因此该操作无效。相反,你想使用。 如文档中所述,对于低于python 2.7的版本,你可以使用此配

  • 问题内容: 我正在寻找一个有序的关联数组,即有序的字典的可靠实现。我想要按键而不是插入顺序排序。 更准确地说,我正在寻找一种int-to-float(或另一种用例是string-to-float)映射结构的节省空间的实现,该结构的结构是: 有序迭代为O(n) 随机访问为O(1) 我想到的最好的方法是将字典和键列表粘合在一起,使最后一个键按等分和插入顺序排列。 还有更好的主意吗? 问题答案: “随机

  • 我试图找到或开发Python的整数分区代码。 仅供参考,整数分区将给定的整数n表示为小于n的整数之和。例如,整数5可以表示为 我已经找到了很多解决方案。http://homepages.ed.ac.uk/jkellehe/partitions.php和http://code.activestate.com/recipes/218332-generator-for-integer-partition