比方说,我给了数组{1, 2, 3, 4}
,n(数组的大小)的范围是2到18。我需要找到所有成对排列这些元素的方法。因此,对于此示例,我将得到:
(1, 2), (3, 4)
(1, 3), (2, 4)
(1, 4), (2, 3)
所以顺序在这里很重要,因为我不想/不需要生成配对相同的所有排列(我认为吗?)。 (例如(1, 2), (3, 4)
和(3, 4), (1, 2)
。)
我已经尝试了一种递归回溯的方法,但是对于较大的数组(14-18)来说,这并不是真正有效的时间安排,对于所有可能的输入,我需要不到2s的执行时间。
这是我的代码:
void gen_sol(int k)
{
if(k > n)
{
//do further calculations
}
else
{
for(int i = 1; i <= n; i++)
{
for(int j = i + 1; j <= n; j++)
{
if(k == 1)
{
if(!used[i] && !used[j])
{
sol[k] = v[i];
sol[k + 1] = v[j];
used[i] = true;
used[j] = true;
gen_sol(k + 2);
used[i] = false;
used[j] = false;
}
}
else
{
if(sol[k - 2] < v[i] && !used[i] && !used[j])
{
sol[k] = v[i];
sol[k + 1] = v[j];
used[i] = true;
used[j] = true;
gen_sol(k + 2);
used[i] = false;
used[j] = false;
}
}
}
}
}
}
现在我知道简短的,描述性的名称通常会被皱眉,但是在竞争激烈的编程环境中,我认为这并不算太糟糕。因此k
表示递归级别/我正在使用的当前对,sol
是我在其中构建当前排列的数组,used
用于指示其中的哪些元素我已经使用过的数组。
关于实际的货币对生成,我正在将当前可能的货币对与上一个货币对进行比较,以查看其按字典顺序排序。我知道我可以在循环中合并两个单独的if语句,我应该这样做。
我已经考虑过尝试一种迭代方法,但是使用此方法时n = 18的执行时间太长了,我认为进行迭代不会有太大帮助。
也许有一种方法可以减少一个循环吗?