简体   繁体   English

如何在C ++中更有效地仅生成这么多排列?

[英]How to generate only so many permutations more efficiently in C++?

I'm trying to solve a problem and I feel like I'm really close to it but it's still a little slow because I'm generating so many permutations. 我正在尝试解决一个问题,我觉得自己已经很接近了,但是它仍然有点慢,因为我生成了很多排列。

I need the permutations of "0123456789". 我需要“ 0123456789”的排列。 I know there are (10)! 我知道有(10)! permutations which is a lot. 排列很多。 I use an std::unordered_set because I don't care about the order they are stored in and it seemed faster than using a regular std::set 我使用std::unordered_set是因为我不在乎它们的存储顺序,而且看起来比使用常规std::set更快

Here is some core I wrote: max_perm_size is the size of the string of permutations I care about for a particular case. 这是我写的一些核心内容: max_perm_size是我在特定情况下关心的排列字符串的大小。

void getPermutations(unordered_set<string> &permutations, int &max_perm_size)
{
    string digits = "0123456789";

    do{

        permutations.insert(digits.substr(0, max_perm_size));

    } while (next_permutation(digits.begin(), digits.end()));

}

I have two main questions about this code: 关于此代码,我有两个主要问题:

  1. Above I'm still generating then entire "0123456789" permutation even for cases where I only care about permutations of size max_perm_size . 在上面,即使对于仅关心max_perm_size大小的排列的情况,我仍然会生成整个“ 0123456789”排列。 I just trim them afterwords before storing them into my std::unordered_set . 在将它们存储到我的std::unordered_set之前,我只是对它们进行了修剪。 Is there a way to do this in a better way so it's faster? 有没有办法更好地做到这一点,从而更快?
  2. For the worst case max_pem_size = 10 , is there a more efficient way for me to generate and store all of these permutations in general? 在最坏的情况下, max_pem_size = 10 ,对于我而言,是否有一种更有效的方式来生成和存储所有这些排列?

As far as a I can tell, your result is numbers (without repeated digits) from 0 through some limit. 据我所知,您的结果是从0到某个限制的数字(没有重复的数字)。 Since you say you don't care about the order of the digits, it's probably easiest if we just stick to ascending ones. 既然您说您不关心数字的顺序,那么如果我们只坚持升序,那可能是最简单的。 That being the case, we can generate results like this: 在这种情况下,我们可以生成如下结果:

#include <iostream>

int main() {
    for (int i=0; i<10; i++)
        for (int j=i+1; j<10; j++)
            for (int k=j+1; k<10; k++)
                std::cout << i << j << k << "\t";
}

Result: 结果:

012     013     014     015     016     017     018     019     023     024     025     026     027
028     029     034     035     036     037     038     039     045     046     047     048     049
056     057     058     059     067     068     069     078     079     089     123     124     125
126     127     128     129     134     135     136     137     138     139     145     146     147
148     149     156     157     158     159     167     168     169     178     179     189     234
235     236     237     238     239     245     246     247     248     249     256     257     258
259     267     268     269     278     279     289     345     346     347     348     349     356
357     358     359     367     368     369     378     379     389     456     457     458     459
467     468     469     478     479     489     567     568     569     578     579     589     678
679     689     789

If your limit isn't a number of digits, you can put the digits together into an actual int and compare (then break out of the loops). 如果您的限制不是数字位数,则可以将这些数字放到一个实际的int中进行比较(然后脱离循环)。

This is specific to your case, not a general solution, but for the case of digit permutations, you can do: 这是针对您的情况而不是通用的解决方案,但是对于数字排列的情况,您可以执行以下操作:

void getPermutations(unordered_set<string> &permutations, int max_perm_size)
{
    if (max_perm_size < 1) return;

    uint64_t stopat = 1;
    for (int i = 1; i < max_perm_size; ++i) {
        stopat *= 10;
    }

    for (uint64_t dig = 0; dig < stopat; ++dig) {
        std::ostringstream ss;
        ss << std::setw(max_perm_size) << std::setfill('0') << dig;
        permutations.insert(ss.str());
    }
}
  1. You can take a substring of your digits string first. 您可以先获取数字字符串的子字符串。 Then your loop will only deal with permutations of max_perm_size. 然后,您的循环将仅处理max_perm_size的排列。

  2. You could create a class that generates permutations on demand instead of pre-generating and storing them beforehand. 您可以创建一个按需生成排列的类,而不是预先生成并存储它们。 Depending on your application, you may not even have to store them. 根据您的应用程序,您甚至不必存储它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM