我编写了一个程序,解决了24的通用版本(为好奇的人提供链接)。也就是说,给定一组n
数,有没有办法对它们执行二进制运算,以便它们计算到目标数。
为此,我将可能的表达式视为由'v'
或'o'
组成的char数组,其中'v'
是值的占位符,'o'
是操作的占位符。请注意,如果有n
值,则必须有n-1
操作。
程序当前的工作方式是按字典顺序检查{'o','o',…,'v', v'…}
的每个排列,并查看前缀表达式是否有效。例如,当n=4
时,以下表达式被认为是有效的:
{'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'}
我的问题是,是否存在一种有效的算法来得到在某种排序中有效的下一个排列?目标是消除检查表达式是否对每个排列都有效的必要。
此外,如果存在这样的算法,是否存在计算第k个有效置换的O(1)
时间?
我假设长度为< code>2n-1的前缀表达式< code>A当且仅当
操作数
其中<code>0
此外,这意味着确实存在
(1/n)C(2n-2,n-1)
有效置换,其中C(n,k)是
。
下面是如何生成ov
-模式。下面代码背后的细节在Knuth第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)。神奇的单词是解开二叉树的等级。
下一个排列 问题描述 这道题是 LeetCode 31题。 “下一个排列”的定义是:给定数字序列的字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。 我们可以将该问题形式化地描述为:给定若干个数字,将其组合为一个整数。如何将这些数字重新排列,以得到下一个更大的整数。如 123 下一个更大的数为 132。如果没有更大的整数,则输出最小的整数。 以 1,
注意:我不想使用任何库。试图解决https://icpc.kattis.com/problems/stacking 在以下条件下,合并排序数组所需的最小操作数是多少: 拆分:可以将单个堆栈拆分为两个堆栈,方法是将堆栈的任何顶部提起并放在一边,形成一个新堆栈。 连接:两个堆栈可以通过将一个放在另一个上面来连接。仅当顶部堆叠的底板不大于底部堆叠的顶板时,才允许这样做,也就是说,必须正确订购连接的堆叠。
有一个集合,例如(1,4,2,5,7,6,9,8,3)。我们通过以下方式计算它的(FD):。inputArray是原始集。例如大小写为(1,4,2,5,7,6,9,8,3)。first差异是从inputArray创建的,方法如下:(inputArray的第二个元素)-(inputArray的第一个元素)等等。 所以给定集合的FD是(3,-2,3,2,-1,3,-1,-5)。任务是找到给定集合的多个
我有一个数字 1 到 n 的排列,在每个回合中,一个排列函数用于将当前排列映射到新的排列。 该函数由定义,它将当前置换的每个元素映射到新置换中的一个位置。由于这个函数是内射和满射的,可以证明我们总是再次得到第一个置换。(这实际上是排列图中的一个循环) 例如
我需要一个生成置换的算法或伪代码。假设给我两个数字,表示字母的数量和排列的数量。 我必须编写26个英文字母的所有排列。我写了一段代码,但有一个问题。问题是对于输入3和6,我的代码生成ABC、ACB、BAC、BCA、CBA、CAB。但我需要它来生成ABC、ACB、BAC、BCA、CAB、CBA。
给定 n,求 m 使得 m 是大于 n 的最小半素数。 下一个素数相当简单,而半素数则不那么简单。需要明确的是,只需要半素数,尽管同时获得因子会很方便。 我想到了一些方法,但我相信有更好的方法。 假设算术运算为O(1)。我使用了埃拉托斯特尼筛,它是O(n log log n),我知道阿特金筛,但我喜欢我的半优化埃拉托斯特尼。 从n开始计数,当你找到一个半素数时停止。 这看起来很愚蠢,但如果有一个O