给定数字k,找到设置n位为1 <= n <= k的k位数字的所有可能组合。解决方案应首先打印所有带有一个置位的数字,然后再打印带有两个置位的数字,直到所有其k位都已设置的数字。如果两个数字具有相同的置位位数,则应首先使用较小的数字。
例子:
Input: K = 3
Output:
001 010 100
011 101 110
111
Input: K = 4
Output:
0001 0010 0100 1000
0011 0101 0110 1001 1010 1100
0111 1011 1101 1110
1111
Input: K = 5
Output:
00001 00010 00100 01000 10000
00011 00101 00110 01001 01010 01100 10001 10010 10100 11000
00111 01011 01101 01110 10011 10101 10110 11001 11010 11100
01111 10111 11011 11101 11110
11111
我们需要找到k位数字与n个设置位的所有可能组合,其中1 <= n <= k。如果我们仔细分析,我们会发现问题可以进一步分为子问题。通过将长度k-1和n-1的所有组合都前缀0,并将长度k-1和n-1的所有组合都加上1,可以找到长度为k和n的所有组合。我们可以使用动态编程来保存子问题的解决方案。
以下是上述想法的C++实现–
// C++ program find all the possible combinations of
// k-bit numbers with n-bits set where 1 <= n <= k
#include
#include
using namespace std;
// maximum allowed value of K
#define K 16
// DP lookup table
vector DP[K][K];
// Function to find all combinations k-bit numbers with
// n-bits set where 1 <= n <= k
void findBitCombinations(int k)
{
string str = "";
// DP[k][0] will store all k-bit numbers
// with 0 bits set (All bits are 0's)
for (int len = 0; len <= k; len++)
{
DP[len][0].push_back(str);
str = str + "0";
}
// fill DP lookup table in bottom-up manner
// DP[k][n] will store all k-bit numbers
// with n-bits set
for (int len = 1; len <= k; len++)
{
for (int n = 1; n <= len; n++)
{
// prefix 0 to all combinations of length len-1
// with n ones
for (string str : DP[len - 1][n])
DP[len][n].push_back("0" + str);
// prefix 1 to all combinations of length len-1
// with n-1 ones
for (string str : DP[len - 1][n - 1])
DP[len][n].push_back("1" + str);
}
}
// print all k-bit binary strings with
// n-bit set
for (int n = 1; n <= k; n++)
{
for (string str : DP[k][n])
cout << str << " ";
cout << endl;
}
}
// Driver code
int main()
{
int k = 5;
findBitCombinations(k);
return 0;
}
输出:
00000
00001 00010 00100 01000 10000
00011 00101 00110 01001 01010 01100 10001 10010 10100 11000
00111 01011 01101 01110 10011 10101 10110 11001 11010 11100
01111 10111 11011 11101 11110
11111