生成 0, 1,...n-1, n 个 k 数的所有可能组合。每个组合应按升序排列[重复]

Posted

技术标签:

【中文标题】生成 0, 1,...n-1, n 个 k 数的所有可能组合。每个组合应按升序排列[重复]【英文标题】:Generate all possible combinations in 0, 1,...n-1, n of k numbers. Each combination should be in ascending order [duplicate] 【发布时间】:2015-08-22 17:35:21 【问题描述】:

请理解这不是重复的问题。这个问题需要排序组合。请阅读之前的问题。 该组合可以有一个数字的重复。目前,我已经尝试生成 n-k+1 0 和 k 1 的排列。但它不会产生带有重复的组合。例如: 从 0, 1,....n 中选择 3 个数字,生成 9 种组合:

(0 1 2),
(0 1 3),
(0 1 4),
(0 2 3),
(0 3 4),
(1 2 3),
(1 2 4),
(1 3 4),
(2 3 4)

我也需要包含这些组合:

(0, 0, 0),
(0, 0, 1),
(0, 0, 2),
(0, 0, 3),
(0, 0, 4),
(0, 1, 1),
(0, 2, 2),
(0, 3, 3),
(0, 4, 4),
(1, 1, 1),
(1, 1, 2),
(1, 1, 3),
(1, 1, 4),
(1, 2, 2),
(1, 3, 3),
(1, 4, 4),
(2, 2, 2),
(2, 2, 3),
(2, 2, 4),
(2, 3, 3),
(2, 4, 4),
(3, 3, 3),
(3, 3, 4),
(3, 4, 4),
(4, 4, 4)

获得此结果的最有效方法是什么?我现在使用 next_permutation 来生成组合。请看:

    vector<ll> nums, tmp;
    for(i = 0; i <= m - n; i++)
    
        nums.push_back(0);
    
    for(i = 0; i < n; i++)
    
        nums.push_back(1);
    
    do 
    
        tmp.clear();
        for(i = 0; i <= m; i++)
        
            if(nums[i] == 1)
            
                tmp.push_back(i);
            
        
        for(i = 0; i < tmp.size(); i++)
        
            cout << tmp[i] << " ";
        
        cout << endl;
     while(next_permutation(nums.begin(), nums.end()));

【问题讨论】:

`std::next_permutation' 天真的解决方案?三个嵌套循环。 了解为什么您需要此结果以及您迄今为止取得的成就会很有帮助。如果是课程作业则更是如此,因为您不太可能从非家庭作业的答案中学习。 顺便说一句,你知道combinations 和permutation 相互矛盾吗? @TobySpeight 我确实意识到了这一点。这不是家庭作业。 【参考方案1】:

您的“组合”本质上是基数 N 数字系统中的 k 位数字。有 N^k 个这样的数字。

生成它们的最简单方法是递归。

您还可以在0..N^k-1 范围内组织简单的for-cycle,并在上述系统中表示循环计数器。伪代码

for (i=0; i<N^k; i++)    //N^k is Power, not xor
   t = i 
   d = 0
   digit = 0
   while t > 0 do 
      digit[d++] = t%N //modulus
      t = t / N    //integer division
   
   output digit array

【讨论】:

【参考方案2】:

以下可能会有所帮助:

bool increment(std::vector<int>& v, int maxSize)

    for (auto it = v.rbegin(); it != v.rend(); ++it) 
        ++*it;
        if (*it != maxSize) 
            return true;
        
        *it = 0;
    
    return false;

用法:

std::vector<int> v(3);

do 
    // Do stuff with v
 while (increment(v, 10));

Live demo

【讨论】:

每个组合都需要排序。

以上是关于生成 0, 1,...n-1, n 个 k 数的所有可能组合。每个组合应按升序排列[重复]的主要内容,如果未能解决你的问题,请参考以下文章

number 的单调性证明

noip2016 组合数问题

数的划分与放苹果问题

Day 2 T1

Noip2016day2 组合数问题problem

NOIP2016D2T1 组合数问题