部分排列

2024-01-07

我有以下递归函数用于输出部分组合:

void comb(string sofar, string rest, int n) {

    string substring;

    if (n == 0)
        cout << sofar << endl;
    else {
        for (size_t i = 0; i < rest.length(); i++) {
            substring = rest.substr(i + 1, rest.length());
            comb(sofar + rest[i], substring, n - 1);
        }
    }
}

像这样调用:

comb("", "abcde", 3);

通过部分组合,我的意思是它使用 n 个选择和 r 个元素(而不是 n 个选择、n 个元素)。

但是,我想考虑元素的顺序(即排列)。我可以找到许多完整排列的算法,但不是部分排列。


现在是进行性能现实检查的时候了。如果您只对一次访问 5 件事 3 的排列感兴趣,请立即停止阅读,因为访问次数太少了,这并不重要(除非您可能已经这样做了十亿次)。

但如果您需要访问更多的东西,并且一次访问更多的东西,性能就真的开始变得重要了。例如,访问 26 个字符串:“abcdefghijklmnopqrstuvwxyz”,一次六个项目怎么样?随着排列,成本增长得非常快......

对于性能测试,最好注释掉终端的输出,因为这往往是一个非常慢的操作,会淹没其他所有内容。

这个答案 https://stackoverflow.com/a/34867494/576911(目前接受的)看起来像这样:

#include <chrono>
#include <iostream>
#include <string>

using std::string;
using std::cout;

void comb(string sofar, string rest, int n)
{
    // std::cout << "comb('" << sofar << "', '" << rest << "', " << n << ")\n";
    string substring;

    if (n == 0)
        ; //cout << sofar << '\n';
    else {
        for (size_t i = 0; i < rest.length(); i++) {
            substring = rest.substr(0, i) + rest.substr(i + 1, rest.length());
            comb(sofar + rest[i], substring, n - 1);
        }
    }
}

int main()
{
    std::string s("abcdefghijklmnopqrstuvwxyz");
    auto t0 = std::chrono::steady_clock::now();
    comb("",s, 6);
    auto t1 = std::chrono::steady_clock::now();
    std::cout << std::chrono::duration<double>{t1-t0}.count() << '\n';
}

在我的系统上(clang++ -std=c++14 test.cpp -O3)输出:

14.2002

这个答案使用std::next_permutation https://stackoverflow.com/a/34868103/576911明显更快。

#include <algorithm>
#include <chrono>
#include <iostream>

// Requires: sequence from begin to end is sorted
//           middle is between begin and end
template<typename Bidi, typename Functor>
void for_each_permuted_combination(Bidi begin,
                                   Bidi middle,
                                   Bidi end,
                                   Functor func) {
  do {
    func(begin, middle);
    std::reverse(middle, end);
  } while (std::next_permutation(begin, end));
}

int
main()
{
    std::string s("abcdefghijklmnopqrstuvwxyz");
    auto t0 = std::chrono::steady_clock::now();
    for_each_permuted_combination(s.begin(), s.begin()+6, s.end(),
        [](auto first, auto last)
        {
//             for (; first != last; ++first)
//                 std::cout << *first;
//             std::cout << '\n';
        });
    auto t1 = std::chrono::steady_clock::now();
    std::cout << std::chrono::duration<double>{t1-t0}.count() << '\n';
}

其输出:

8.39237

这快了 69%!这种速度的提高很大程度上可以归因于第一个算法中隐含的分配和释放的缺乏。

不过我想指出更快的算法 http://howardhinnant.github.io/combinations.html.

驱动程序看起来像:

#include "combinations"
#include <chrono>
#include <iostream>
#include <string>

int
main()
{
    std::string s("abcdefghijklmnopqrstuvwxyz");
    auto t0 = std::chrono::steady_clock::now();
    for_each_permutation(s.begin(), s.begin()+6, s.end(),
        [](auto first, auto last)
        {
//             for (; first != last; ++first)
//                 std::cout << *first;
//             std::cout << '\n';
            return false;
        });
    auto t1 = std::chrono::steady_clock::now();
    std::cout << std::chrono::duration<double>{t1-t0}.count() << '\n';
}

输出是:

0.2742

This is 快 30 倍 than 答案使用std::next_permutation https://stackoverflow.com/a/34868103/576911 and 快 51 倍 than 目前接受的答案 https://stackoverflow.com/a/34867494/576911!并作为n and r随着增长,这些性能数字的差异也会增大。

The 链接库 http://howardhinnant.github.io/combinations.html是免费且开源的。实现位于链接处,可以从中复制/粘贴。我不会说这很简单。我只是声称它的性能令人信服。性能差异是如此巨大,以至于它可以决定问题能否在实际时间内得到解决。

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

部分排列 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • Maven 程序集插件模块集源指令不包含任何文件并且与包含的模块不匹配

    我有一个多模块 Maven 项目 我正在尝试让程序集插件的模块集源部分正常工作 我有模块 模块父模块 module a and 模块组件 module a and 模块组件是的孩子模块父模块 模块组件已声明 pom 依赖项module a
  • 如何从 vcpkg 检索 cmake 目标名称?

    安装软件包后 vcppkg 非常有帮助地显示相关的 CMake 目标 libwebp x64 windows 包提供了 CMake 目标 find package WebP CONFIG REQUIRED target link libra
  • 相当于hadoop中mongo的out:reduce选项

    我正在重写 MongoDB 映射缩减作业以使用 Hadoop 使用 mongo hadoop 连接器 但是当我将两个数据集映射到同一个集合时 它会覆盖这些值而不是使用它们 reduce collectionName 如果结果集中和旧集合中存
  • 在 R 中制作分区统计图:合并来自多个州的邮政编码形状文件

    受到这里帖子的激励 使用 R 开发地理专题图 https stackoverflow com questions 1260965 developing geographic thematic maps with r 我正在考虑构建基于邮政编
  • 从 ActiveRecord/Rails 查询中检索单个记录

    我发出如下查询 精确检索 0 或 1 条记录 car Car where vin 1234567890abcdefg 返回的当然是长度为 1 的汽车列表 所以我最终添加 first在查询末尾 car Car where vin 123456
  • 在 UITabBarController 上的选项卡之间共享背景视图

    是否可以在 UITabBarController 上的选项卡之间具有相同的背景 而不必在所有视图上设置相同的背景 我想在后台放置一个视图 定期执行非常短的非资源密集型动画 切换选项卡时 我希望该动画能够持续存在 我已经阅读了如何为 UINa
  • JavaScript 中的节点是什么?

    我想知道 JavaScript 中的节点到底是什么 如函数中所示 element nodeType row parentNode removeChild row 在这种情况下 节点 只是一个 HTML 元素 DOM 是代表网站 HTML 的
  • Fiware Ultralight 2.0 IoTAgent:如何从设备发送测量?

    我正在研究一个 POC 使用 Fiware 平台创建智能城市物联网项目 我正在尝试运行端到端流程 我正在运行以下 Docker 容器 容器 ID 端口名称 24f036202f78 0 0 0 0 4041 gt 4041 tcp 0 0
  • 如何为自定义 Java 标记添加 Eclipse 快速修复?

    我想向 Eclipse 的问题视图报告 Java 文件的自定义问题并为它们提供快速修复 标准方法是使用扩展点org eclipse core resources markers声明自定义标记并通过调用添加标记org eclipse core
  • 在 VS 设计器中加载包时禁用 SSIS 包验证

    我有一些部署到 SQL 2005 Server 的 SSIS 包 随后在 Visual Studio 2003 中设计和维护 当我打开任何 BIDS 项目以及其中一个包时 设计器总是验证每个数据流和任务目的 通常 这不是问题 但是 在某些情
  • Jasmine单元测试observable订阅不触发

    我将 Angular 5 与 Jasmine 和 Karma 一起使用 我正在尝试测试某个功能是否有效 但我的订阅在单元测试期间没有触发 这导致我的单元测试失败 因为我正在使用 jasmine 的 did 函数 我想让这个单元测试成功 我已
  • Tomcat 中的 NIO 连接器

    我试图通过配置 server xml 文件在 Tomcat 6 0 中启用 NIO 连接器 但我得到Firefox 无法与位于 localhost 8081 的服务器建立连接 每当我输入时在浏览器中本地主机 8081 这就是我在 Tomca
  • DataGridTextColumn - 如何绑定IsReadonly?

    在 Silverlight 4 中 DataGridTextColumn 的 IsReadOnly 属性似乎不是依赖属性 因此我无法将它绑定到视图模型上的属性 似乎唯一的选择是使用 DataTemplate 但即使在这里我也面临两个主要问题
  • 用循环填充矩阵

    我正在尝试创建一个矩阵n by k with kmvn 使用循环进行协变量 非常简单 但到目前为止还没有工作 这是我的代码 n 1000 k 5 p 100 mu 0 sigma 1 x matrix data NA nrow n ncol
  • 如何在 laravel eloquent 中添加两列值并执行 where 条件

    这是我的桌子 id remaining amount additional amount 1 200 0 2 100 100 3 300 100 4 200 50 我正在尝试获取总和为剩余数量 额外金额 gt 0 result this g
  • 响应 SwiftUI 中的按键事件

    我想响应按键 例如esc键在 macOS OSX 上 以及在 iPad 上使用外部键盘时 我怎样才能做到这一点 我想过用 available available与 SwiftUI 的onExitCommand https developer
  • 一行中没有所有 True 值的布尔数组

    I have numpy array np random seed 100 mask np random choice True False size 10 3 print mask True True False False False
  • 如何在 git url 的用户名或密码中转义“@”

    在命令行上推送到 git 的格式之一是 Url format https username password github com owner repo 我的挑战是用户名和密码 这是我无法控制的共享帐户 包含 在他们里面 实际上都是 在这种
  • Spring-Boot Jersey:允许 Jersey 提供静态内容

    该应用程序使用 JDK 8 Spring Boot 和 Spring Boot Jersey 启动器 并打包为 WAR 尽管它是通过 Spring Boot Maven 插件在本地运行 我想做的是将我动态 在构建时 生成的文档作为欢迎页面
  • 部分排列

    我有以下递归函数用于输出部分组合 void comb string sofar string rest int n string substring if n 0 cout lt lt sofar lt lt endl else for s