下一个词法"permutation"算法
Next lexical "permutation" algorithm
我写了一个程序来解决24的通用版本(好奇者的链接(。也就是说,给定一组n
数字,有没有办法对它们执行二进制操作,以便它们计算到目标数字。
为此,我将可能的表达式视为由 'v'
或 'o'
组成的 char 数组,其中 'v'
是值的占位符,'o'
是操作的占位符。请注意,如果存在n
值,则必须有n-1
操作。
该程序目前的工作方式是按字典顺序检查{'o','o',...,'v',v'...}
的每个排列,并查看前缀表达式是否有效。例如,当n = 4
时,以下表达式被视为有效:
{‘o’,’o’,’o’,’v’,’v’,’v’,’v’}
{‘o’, ‘v’, ‘o’, ‘v’, ‘o’, ‘v’, ‘v’}
以下表达式无效:
{‘v’,’o’,’v’,’o’,’o’,’v’,’v’}
{‘o’,’o’,’v’,’v’,’v’,’o’,’v’}
我的问题是,是否存在一种有效的算法来获得在某种排序中有效的下一个排列?目标是消除必须检查表达式是否对每个排列都有效。
此外,如果存在这样的算法,是否存在O(1)
时间来计算第 k
个有效排列?
到目前为止我有什么
我假设长度2n-1
的前缀表达式A
被认为是有效的,当且仅当
每个A[i:2n-1)
number of operations < number of values
其中0<=i<2n-1
(从 i
开始,在 2n-1
结束(非包含(的子数组(
此外,这意味着C(n,k)
n choose k
的地方正好存在(1/n)C(2n-2,n-1)
有效的排列。
下面介绍如何生成ov
模式。以下代码背后的细节在高德纳第 4A 卷中(或至少提到;我可能做了其中一个练习(。您可以使用现有的排列机制在更改模式之前以各种方式排列值。
代码
#include <cstdio>
namespace {
void FirstTree(int f[], int n) {
for (int i = n; i >= 0; i--) f[i] = 2 * i + 1;
}
bool NextTree(int f[], int n) {
int i = 0;
while (f[i] + 1 == f[i + 1]) i++;
f[i]++;
FirstTree(f, i - 1);
return i + 1 < n;
}
void PrintTree(int f[], int n) {
int i = 0;
for (int j = 0; j < 2 * n; j++) {
if (j == f[i]) {
std::putchar('v');
i++;
} else {
std::putchar('o');
}
}
std::putchar('v');
std::putchar('n');
}
}
int main() {
constexpr int kN = 4;
int f[1 + kN];
FirstTree(f, kN);
do {
PrintTree(f, kN);
} while (NextTree(f, kN));
}
生成输出
ovovovovv
oovvovovv
ovoovvovv
oovovvovv
ooovvvovv
ovovoovvv
oovvoovvv
ovoovovvv
oovovovvv
ooovvovvv
ovooovvvv
oovoovvvv
ooovovvvv
oooovvvvv
有一种方法可以得到第 k 棵树,但时间是 O(n( 而不是 O(1(。魔术词是无排名的二叉树。
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- std::unordered_map 搜索算法是如何实现的?
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 下一个词法"permutation"算法