如何生成 a[i] != i 的排列?

2023-11-25

假设我有一个整数数组int a[] = {0, 1, ... N-1}, where N的大小是a。现在我需要生成所有排列a s that a[i] != i对全部0 <= i < N。你会怎么做?


下面是一些 C++ 实现的算法,该算法基于递归的双射证明

!n = (n-1) * (!(n-1) + !(n-2)),

where !n是混乱的数量n items.

#include <algorithm>
#include <ctime>
#include <iostream>
#include <vector>

static const int N = 12;
static int count;

template<class RAI>
void derange(RAI p, RAI a, RAI b, int n) {
    if (n < 2) {
        if (n == 0) {
            for (int i = 0; i < N; ++i) p[b[i]] = a[i];
            if (false) {
                for (int i = 0; i < N; ++i) std::cout << ' ' << p[i];
                std::cout << '\n';
            } else {
                ++count;
            }
        }
        return;
    }
    for (int i = 0; i < n - 1; ++i) {
        std::swap(a[i], a[n - 1]);
        derange(p, a, b, n - 1);
        std::swap(a[i], a[n - 1]);
        int j = b[i];
        b[i] = b[n - 2];
        b[n - 2] = b[n - 1];
        b[n - 1] = j;
        std::swap(a[i], a[n - 2]);
        derange(p, a, b, n - 2);
        std::swap(a[i], a[n - 2]);
        j = b[n - 1];
        b[n - 1] = b[n - 2];
        b[n - 2] = b[i];
        b[i] = j;
    }
}

int main() {
    std::vector<int> p(N);
    clock_t begin = clock();
    std::vector<int> a(N);
    std::vector<int> b(N);
    for (int i = 0; i < N; ++i) a[i] = b[i] = i;
    derange(p.begin(), a.begin(), b.begin(), N);
    std::cout << count << " permutations in " << clock() - begin << " clocks for derange()\n";
    count = 0;
    begin = clock();
    for (int i = 0; i < N; ++i) p[i] = i;
    while (std::next_permutation(p.begin(), p.end())) {
        for (int i = 0; i < N; ++i) {
            if (p[i] == i) goto bad;
        }
        ++count;
    bad:
        ;
    }
    std::cout << count << " permutations in " << clock() - begin << " clocks for next_permutation()\n";
}

在我的机器上,我得到

176214841 permutations in 13741305 clocks for derange()
176214841 permutations in 14106430 clocks for next_permutation()

恕我直言,这是一种洗涤。可能双方都需要做出改进(例如,重新实施next_permutation通过仅扫描发生变化的元素的混乱测试);这留给读者作为练习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何生成 a[i] != i 的排列? 的相关文章

  • 缓存感知树的实现

    I have a tree where every node may have 0 to N children 用例是以下查询 给定指向两个节点的指针 这些节点是否位于树的同一分支内 Examples q 2 7 gt true q 5 4
  • 在小于 O(n) 的时间内检查凸多边形交集?

    我有 2 个凸多边形 2d 我想检查这 2 个多边形是否相交 事实上 我会多次移动和旋转多边形 所以我也可以做一些预计算来获得这个问题的快速答案 我正在寻找一种低复杂度的算法 我知道可以检查一个点是否位于 O log n 的凸多边形中 我想
  • 我可以在线性时间内检查有界列表是否包含重复项吗?

    假设我有一个Int列表 其中元素已知是有界的 并且列表已知不长于它们的范围 因此它完全有可能不包含重复项 如何才能最快地测试是否是这种情况 我知道nubOrd https hackage haskell org package contai
  • 查找按降序排序的向量中严格小于某个键的第一个元素

    据我了解 可以使用 find if STL 算法函数来完成此任务 如下所示 long long int k k key scanf lld k auto it find if begin v end v k auto e return e
  • 在哪里可以找到产生无标头输出的无损压缩算法?

    你们中有人知道产生无标头输出的无损压缩算法吗 例如不存储用于压缩的哈夫曼树吗 我不是谈论硬编码的霍夫曼树 但我想知道是否有任何算法可以压缩和解压缩输入而不在其输出中存储一些元数据 或者这在理论上是不可能的吗 当然是可能的 其中 LZ 系列压
  • 全部配对图表上的所有路径

    这可能是一个没有最佳解决方案的问题 假设我有一个有向图 不知道它是否有循环 循环检测将是这个问题的方面之一 给定一组顶点 可能是数百万个顶点 我需要计算给定图的所有唯一对之间的所有不同路径 没有重复顶点的路径 我该如何应对这种情况 让我们看
  • 是否有任何算法可以计算给定定义形状的坐标的形状面积?

    所以我有一些接收 N 个随机数的函数2D点 是否有任何算法可以计算输入点定义的形状面积 你想要计算多边形的面积 http local wasp uwa edu au pbourke geometry polyarea 取自链接 转换为 C
  • 在数组中出现超过 n/3 次的数字

    我读过这个问题查找数组中最常见的条目 https stackoverflow com questions 278488 puzzle find the most common entry in an array 乔恩 斯基特的回答真是令人兴
  • GO中的优先级队列

    谁能向我解释一下 我想在GO中实现一个优先级队列 接口实现来自link https golang org pkg container heap example priorityQueue 但优先级最低 我的代码 pq make Priori
  • 为数据集生成随机 JSON 结构排列

    我想生成 JSON 结构的许多不同排列作为同一数据集的表示 最好不需要对实现进行硬编码 例如 给定以下 JSON name smith occupation agent enemy humanity nemesis neo 应该产生许多不同
  • 根据先前日期进行预测:值数据

    我有一些类似时期的数据集 这是当时人们的介绍 时间大约有一年 数据并不是定期收集的 而是相当随机的 每年 15 30 个条目 来自 5 个不同的年份 The graph drawn from the data for each year l
  • 用于查找遍历图中所有顶点的路线的更好算法是什么?

    所以我有以下问题 给定 x x y 维度的网格 计算路线数 穿过它 从一个角开始 假设左上角 并结束于 另一个 右下 并穿过每个顶点 因此 我当前的方法只是通过尝试每条可能的路径并计算到达终点并遍历每个节点的路径来进行暴力破解 虽然它有效
  • 如何随机打乱地图中的值?

    我有一个 std map 其中键和值均为整数 现在我想随机打乱地图 因此键随机指向不同的值 我尝试了 random shuffle 但它无法编译 请注意 我并没有尝试洗牌键 这对于地图来说没有意义 我正在尝试随机化这些值 我可以将这些值推入
  • 将矩形分组到网格中

    我有一个随机切片的矩形网格 宽度为 80 单位 我已经将网格每一行的可用空间存储在如下数组中 pX 1 sX 15 pX 30 sX 13 pX 43 sX 1 pX 44 sX 17 pX 1 sX 15 pX 16 sX 14 pX 3
  • 检查列表是否已排序的 Pythonic 方法

    有没有一种Python式的方法来检查列表是否已经排序ASC or DESC listtimestamps 1 2 3 5 6 7 就像是isttimestamps isSorted 返回True or False 我想输入一些消息的时间戳列
  • 难题:需要一个不允许排序和/或散列的“复杂”等价关系/分区的示例

    从问题 分区比排序更容易吗 https stackoverflow com questions 3256468 is partitioning easier than sorting 假设我有一个项目列表和一个 它们之间的等价关系 以及 比
  • 在现实生活中,您会使用 heapq Python 模块做什么?

    读完吉多的书后使用 Python 对 2MB RAM 中的一百万个 32 位整数进行排序 http neopythonic blogspot com 2008 10 sorting million 32 bit integers in 2m
  • 如何判断鼠标指针是否位于贝塞尔曲线和直线定义的路径内?

    我有一条由多条贝塞尔曲线和直线段组成的闭合路径 如何判断鼠标指针的当前位置是在路径内部还是外部 Example of mouse leaving the area Example of mouse entering the area 首先
  • 在逻辑回归中使用排名数据

    当我努力学习这些概念时 我将对此给予最大赏金 我正在尝试在逻辑回归中使用一些排名数据 我想使用机器学习来制作一个简单的分类器来判断网页是否 好 这只是一个学习练习 所以我不期望有很好的结果 只是希望学习 过程 和编码技术 我已将数据放入 c
  • Ruby:如何设置枚举器的状态?

    我正在做一个基于 64 的排列增量器 我已经编写了所有工作代码 但是看看 Ruby 已经作为 Array permutation 生成了一个枚举器 我想利用它并更进一步 无需使用 下一个 进行每个排列 我可以设置起点吗 x A Z to a

随机推荐