当前位置: 首页 > 知识库问答 >
问题:

下一个词法“排列”算法

程智明
2023-03-14

我编写了一个程序,解决了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)是


共有1个答案

陶朝明
2023-03-14

下面是如何生成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