我有三个整数变量,只能使用值0
,1
和2
。我想区分我所有三个数字的组合,排序不计算在内。假设变量名为x
,y
和z
。在这种情况下,x=1, y=0, z=0
和x=0, y=1, z=0
以及x=0, y=0, z=1
都是相同的数字,我将此组合称为001
。
现在有一百种方法可以做到这一点,但我要求一个优雅的解决方案,只是出于教育目的。
我想到按位数001
逐位移位:
001 << 0 = 1
001 << 1 = 2
001 << 2 = 4
但数字002
和111
都会给6
。
答案 0 :(得分:7)
移位的想法很好,但你需要 2 位来计算为3.所以尝试移位两次位数:
1 << (2*0) = 1
1 << (2*1) = 4
1 << (2*2) = 16
为所有3个数字添加这些数字,前2位将计算您有多少0
,第二个2位将计算多少1
,第三个2位将计算多少2
{ {1}}。
编辑虽然结果是6位长(每个数字选项0,1,2为2位),但您只需要最低4位作为唯一标识符 - 就好像您知道多少{您拥有{1}}和0
,然后确定1
的数量。
所以不要做
2
你可以做到
res = 1<<(2*x);
res+= 1<<(2*y);
res+= 1<<(2*z);
因为那时
res = x*x;
res+= y*y;
res+= z*z;
因此仅使用4位而不是6位。
答案 1 :(得分:4)
当不同可能性的数量很小时,可以使用查找表。
首先,对三个数字的所有可能组合进行编号,如下所示:
Combinations N Indexes
------------- - ------
000 0 0
001, 010, 100 1 1, 3, 9
002, 020, 200 2 2, 6, 18
011, 101, 110 3 4, 10, 12
012, 021, 102, 120, 201, 210 4 5, 7, 11, 15, 19, 21
022, 202, 220 5 8, 20, 24
111 6 13
112, 121, 211 7 14, 16, 22
122, 212, 221 8 17, 23, 25
222 9 26
第一列显示相同的组合;第二列显示组合的编号(我任意分配);第三列显示每个组合的索引,计算为9*<first digit> + 3*<second digit> + <third digit>
。
接下来,使用此表达式作为索引,为这十种组合中的每一种构建一个查找表:
9*a + 3*b + c
其中a
,b
和c
是您拥有的三个数字。该表如下所示:
int lookup[] = {
0, 1, 2, 1, 3, 4, 2, 4, 5, 1
, 3, 4, 3, 6, 7, 4, 7, 8, 2, 4
, 5, 4, 7, 8, 5, 8, 9
};
这是第一个表的重写,索引处的值对应于列N
中的值。例如,组合号1
位于索引1
,3
和9
;合并2
位于索引2
,6
和18
,依此类推。
要获得组合编号,只需检查
int combNumber = lookup[9*a + 3*b + c];
答案 2 :(得分:1)
对于这么小的数字,最简单的方法就是单独检查它们,而不是试图模仿,例如:
bool hasZero = false;
bool hasOne = false;
bool hasTwo = false;
// given: char* number or char[] number...
for(int i = 0; i < 3; ++i)
{
switch (number[i])
{
case '0': hasZero = true; break;
case '1': hasOne = true; break;
case '2': hasTwo = true; break;
default: /* error! */ break;
}
}
答案 3 :(得分:1)
如果我理解正确,你有一些数字序列可以是1,2或3,其中它们的排列无关紧要(只是不同的组合)。
情况就是这样:
std::vector<int> v{1, 2, 3};
std::sort(v.begin(), v.end());
这将使所有不同的组合保持正确对齐,并且您可以轻松编写循环来测试相等性。
或者,您可以使用std::array<int, N>
(其中N是可能值的数量 - 在本例中为3)。
std::array<int, 3> a;
您要将a[0]
设置为等于1
的数量,a[1]
等于'2的数量等等
// if your string is 111
a[0] = 3;
// if your string is 110 or 011
a[0] = 2;
// if your string is 100 or 010 or 001
a[0] = 1;
// if your string is 120
a[0] = 1;
a[1] = 1;
// if your string is 123
a[0] = 1;
a[1] = 1;
a[2] = 1;
如果您希望将其存储在一个32位整数中:
unsigned long x = 1; // number of 1's in your string
unsigned long y = 1; // number of 2's in your string
unsigned long z = 1; // number of 3's in your string
unsigned long result = x | y << 8 | z << 16;
要检索每个的数量,您可以
unsigned long x = result & 0x000000FF;
unsigned long y = (result >> 8) & 0x000000FF;
unsigned long z = (result >> 16) & 0x000000FF;
这与RBG
宏中发生的情况非常相似。
答案 4 :(得分:1)
int n[3]={0,0,0};
++n[x];
++n[y];
++n[z];
现在,在n数组中,对于x,y,z的每个唯一无序组合,您都有唯一的有序值组合。
例如,x = 1,y = 0,z = 0且x = 0,y = 0,z = 1将给出n = {2,1,0}