按字典顺序排列 1...n 的 k 的组合,算法太慢

Posted

技术标签:

【中文标题】按字典顺序排列 1...n 的 k 的组合,算法太慢【英文标题】:Combinations of k of 1...n in lexycographical order, algorithm too slow 【发布时间】:2020-04-27 15:02:30 【问题描述】:

下面是一种方法(使用回溯),按字典顺序列出区间 [1,n] 中 k 个数字的所有可能组合。不允许重复。 即:

输入:

5 3

输出:

1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5

我想越来越多地构建序列:一旦我将第一个数组元素设置为 1,我只需要从 2 迭代到 e_m - (n - 2) 来获取第二个元素;并且一旦后者达到 3,则第三个元素仅从 4 变为 e_m - (n - 3) 等。 我不知道该怎么做,你能帮忙吗?下面的方法构建了所有n个数≤el_maxim的序列,然后只显示那些增加的..在线编译器不会接受这个,因为它太慢了

#include <iostream>
using namespace std;
int sol[20], n , el_maxim;
void display()

    for (int i = 0; i < n; i++)
        cout << sol[i] << " ";
    cout << endl;

int okay()

    for (int i = 0; i < n - 1; i++)
        if (sol[i] >= sol[i + 1])
            return 0;
    return 1;

void bkt(int poz)

    if (poz == n)
    
        okay();
        if (okay() == 1)
            display();
    
    else
        for (int i = 1; i <= el_maxim; i++)
        
            sol[poz] = i;
            bkt(poz + 1);
        

int main()

    cin >> el_maxim >> n;
    bkt(0);
    return 0;

【问题讨论】:

okay();if (okay() == 1) -- 你为什么要给okay打两次电话? 这能回答你的问题吗? Algorithm to return all combinations of k elements from n 在那里,您将看到许多算法,这些算法就您在此处所做的工作而言更有效。 因为我是一个假人,当我尝试单独检查 if 语句时遇到了一些错误,修复了代码中的一些问题,我认为事先调用函数是我这样做的方法没有错误了 @nultype “Java 中的 OOP,我想在网站上工作”你的意思是 javascript?或者是 Java 和在网站上工作是两件不同的事情。我只是不希望你开始学习 Java 的目的是用它来开发网站。您可以将 Java 用于网站。您可以将任何东西用作后端,但更常见的是使用 Node.js 的 JavaScript 或使用 Django 的 Python。 两个不同的东西,伙计。哈哈,我是菜鸟,但还没有到使用Java for web ^^的水平 【参考方案1】:

这里有一些工作代码。这个想法是记住您使用的最后一个元素,以免再次尝试使用它。您可以使用参数记住函数调用之间的变量。

为了加快速度,您可以删除okay() 函数并在到达pos == n 时始终调用display(),因为可以保证当您到达它时您会得到正确的答案。我在我的代码中这样做了。

#include <iostream>

using namespace std;
int sol[20], n , el_maxim;
void display()

    for (int i = 0; i < n; i++)
        cout << sol[i] << " ";
    cout << endl;

void bkt(int poz, int last_element)

    if (poz == n)
    
         display();
    
    else
        for (int i = last_element + 1; i <= el_maxim; i++)
        
            sol[poz] = i;
            bkt(poz + 1, i);
        
    

int main()

    cin >> el_maxim >> n;
    bkt(0, 0);
    return 0;

【讨论】:

【参考方案2】:

一个简单的详尽搜索就足够了。如果将来不需要数组,我们也可以在O(K) 额外空间中进行操作。

#include <iostream>
#include <vector>

using namespace std;

void foo(vector<int>& sol, int N, int K, int n = 1, int k = 1)

    if (k > K)
    
        for (int e : sol)
            cout << e << ' ';
        cout << endl;
        return;
    

    for (int i = n; i <= N; ++i)
    
        sol.push_back(i);
        foo(sol, N, K, i + 1, k + 1);
        sol.pop_back();
    


int main()

    int N, K;
    cin >> N >> K;

    vector<int> sol;
    foo(sol, N, K);

【讨论】:

使用 endl 它不起作用,对于其中一个测试用例来说太慢了,将其更改为 '\n' 并且它正在工作,谢谢陌生人!

以上是关于按字典顺序排列 1...n 的 k 的组合,算法太慢的主要内容,如果未能解决你的问题,请参考以下文章

生成 0, 1,...n-1, n 个 k 数的所有可能组合。每个组合应按升序排列[重复]

每日一小练——按字典顺序列出全部排列

leetcode算法题基础(四十二) 回溯算法总结

Lotto(DFS处理)

生成1~n的全排列,按字典序输出

算法:按字典顺序在给定索引处查找给定字符串的字谜