AcWing 842.排列数字(dfs)||(next_permutation)

原题链接 : AcWing 842.排列数字

 dfs做法:

#include<iostream>

using namespace std;

int n;
bool vis[10];
int f[10];

void dfs(int k){
    if(k > n) {
        for(int i : f) if(i)cout << i << " ";
        cout << endl;
    }
    else{
        for(int i = 1; i <= n; i++){
            if(!vis[i]){
                vis[i] = true;
                f[k] = i;
                dfs(k + 1);
                vis[i] = false;
            }
        }
    }
}

int main(){
    cin >> n;
    dfs(1);
    return 0;
}

全排列算法:

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

using namespace std;

int main(){
    int n;
    cin >> n;
    vector<int>nums;
    for(int i = 1; i <= n; i++) nums.push_back(i);
    vector<vector<int> >res;
    do{
        res.push_back(nums);
    }while(next_permutation(nums.begin(),nums.end()));
    
    for(vector<vector<int> >::iterator it = res.begin(); it != res.end(); it ++){
        vector<int> tmp;
        tmp = *it;
        for(vector<int>::iterator itt = tmp.begin(); itt != tmp.end(); itt ++){
            cout << *itt << " ";
        }
        cout << endl;
    }
    return 0;
}

 

### next_permutation 算法的使用与实现原理 `next_permutation` 是一种用于生成给定序列的下一个字典序排列算法。它广泛应用于 C++ 标准模板库(STL)中的 `<algorithm>` 头文件中,同时也被许多其他编程语言所支持或模仿其实现方式。该算法的核心思想是通过交换和重排的方式找到当前排列的下一个可能的排列。 #### 使用方法 在 C++ 中,`std::next_permutation` 的基本用法如下: ```cpp #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> nums = {1, 2, 3}; // 打印所有排列 do { for (int num : nums) { std::cout << num << " "; } std::cout << std::endl; } while (std::next_permutation(nums.begin(), nums.end())); return 0; } ``` 上述代码会输出 `{1, 2, 3}` 的所有排列,按字典序顺序排列: ``` 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 ``` `std::next_permutation` 接受两个迭代器作为参数,表示要处理的序列范围,并返回一个布尔值,指示是否成功找到了下一个排列。如果当前已经是最后一个排列,则返回 `false`,否则返回 `true` [^4]。 #### 实现原理 `next_permutation` 的实现基于以下步骤: 1. **查找第一个可以增加的元素**:从右向左遍历数组,找到第一个比其右侧元素小的元素索引 `i`。 2. **查找最小的大于 `nums[i]` 的元素**:继续从右向左遍历,找到第一个大于 `nums[i]` 的元素索引 `j`。 3. **交换这两个元素**:将 `nums[i]` 和 `nums[j]` 交换。 4. **反转后面的子数组**:将 `i+1` 到末尾的所有元素反转,以确保得到的是下一个字典序排列。 以下是 `next_permutation` 的一个简化实现版本: ```cpp template <typename T> bool next_permutation(std::vector<T>& nums) { int n = nums.size(); int i = n - 2; // Step 1: Find the first element that can be increased while (i >= 0 && nums[i] >= nums[i + 1]) { --i; } if (i == -1) { return false; // Already the last permutation } // Step 2: Find the smallest element larger than nums[i] on the right int j = n - 1; while (nums[j] <= nums[i]) { --j; } // Step 3: Swap elements at i and j std::swap(nums[i], nums[j]); // Step 4: Reverse the suffix starting from i+1 std::reverse(nums.begin() + i + 1, nums.end()); return true; } ``` 此函数接受一个 `std::vector<T>` 类型的输入,并返回一个布尔值,表示是否成功生成了下一个排列 [^4]。 #### 时间复杂度分析 - 最坏情况下,每次调用 `next_permutation` 的时间复杂度为 O(n),其中 n 是序列长度。 - 如果需要生成所有排列,则总时间复杂度为 O(n!),因为共有 n! 种不同的排列 [^4]。 #### 应用场景 `next_permutation` 常用于以下场景: - 生成所有可能的排列组合。 - 解决某些组合优化问题,如旅行商问题(TSP)的小规模实例。 - 在测试中枚举所有可能的输入排列。 - 密码学中用于穷举攻击某些有限长度的密码空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值