1384 全排列(回溯)

本文详细解析了如何通过深度优先搜索(DFS)算法实现字符串全排列,并使用C++代码示例展示从遍历所有结果、排序到去重的完整过程。适用于初学者理解并掌握字符串全排列的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1384 全排列

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
收藏
关注
给出一个字符串S(可能有重复的字符),按照字典序从小到大,输出S包括的字符组成的所有排列。例如:S = "1312",
输出为:
 
1123
1132
1213
1231
1312
1321
2113
2131
2311
3112
3121
3211
Input
输入一个字符串S(S的长度 <= 9,且只包括0 - 9的阿拉伯数字)
Output
输出S所包含的字符组成的所有排列
Input示例
1312
Output示例
1123
1132
1213
1231
1312
1321
2113
2131
2311
3112
3121
3211

Dfs 遍历出所有结果,string 数组存出结果, sort对结果进行排序,unique 对结果去重(去重之前需要排序)

#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>

using namespace std; 

#define maxn 400000

string result[maxn]; 
char temp[maxn]; 
char original[maxn]; 

int numbers; 
int len; 

bool visit[maxn]; 

void Dfs(int x) {

    if (x == len) {
        temp[x] = '\0';
        result[numbers++] = temp;
        return;
    }

    for (int i = 0; i < len; i++) {
        
        if (!visit[i]) {
            visit[i] = true; 
            temp[x] = original[i]; 
            Dfs(x + 1);
            visit[i] = false;
        }
    }
}


int main() {

    //cin >> original; 
    while (cin >> original) {
        len = strlen(original);
        numbers = 0; 
        memset(visit, false, sizeof(visit)); 

        Dfs(0);
    
        sort(result, result + numbers); 
        int m = unique(result, result + numbers) -  result; // string 方法去重

        for (int i = 0; i < m; i++) {
            cout << result[i] << endl; 
        }
    }

    return 0; 
}

 

转载于:https://www.cnblogs.com/yi-ye-zhi-qiu/p/9411115.html

### 全排列回溯算法的实现与原理 全排列是指给定一组不重复的数字,返回这些数字的所有可能排列。回溯算法是一种通过探索所有候选解并丢弃不可行的部分来寻找解决方案的方法。以下是关于全排列回溯算法的具体实现和原理分析。 #### 1. 原理概述 回溯算法的核心在于递归地构建解空间树,在每一步尝试所有的可能性,并在满足条件时保存结果。对于全排列问题,可以通过以下逻辑实现: - 使用一个布尔数组 `used` 来标记哪些元素已经被选入当前路径。 - 遍历输入数组中的每一个未被使用的元素,将其加入当前路径。 - 当前路径长度等于输入数组长度时,表示找到一种排列方案,将其存入结果集。 - 移除最后一个加入的元素(即回退),继续尝试其他可能性[^2]。 #### 2. 时间复杂度 假设输入数组的长度为 \( n \),则共有 \( n! \) 种排列方式。每次生成一个新的排列需要复制整个路径,时间开销为 \( O(n) \)。因此,总体时间复杂度为 \( O(n \cdot n!) \)[^1]。 #### 3. Python 实现代码 下面提供了一个基于回溯算法的 Python 版本实现: ```python def permute(nums): result = [] # 存储最终的结果 path = [] # 记录当前路径上的元素 used = [False] * len(nums) # 标记某个位置的元素是否已被使用 def backtrack(): if len(path) == len(nums): # 如果当前路径长度等于输入数组长度,则找到了一种排列 result.append(path[:]) # 将当前路径拷贝一份放入结果集中 return for i in range(len(nums)): # 遍历所有可选项 if not used[i]: # 若该元素尚未被使用 used[i] = True # 标记为已使用 path.append(nums[i]) # 加入当前路径 backtrack() # 继续递归处理下一层 path.pop() # 回退:移除最后加入的元素 used[i] = False # 取消标记 backtrack() return result # 测试用例 nums = [1, 2, 3] print(permute(nums)) ``` #### 4. Java 实现代码 如果更倾向于 Java 的实现方式,可以参考如下代码片段: ```java import java.util.ArrayList; import java.util.List; public class Permutation { List<List<Integer>> res = new ArrayList<>(); public List<List<Integer>> permute(int[] nums) { boolean[] used = new boolean[nums.length]; backtrack(nums, new ArrayList<>(), used); return res; } private void backtrack(int[] nums, List<Integer> path, boolean[] used) { if (path.size() == nums.length) { res.add(new ArrayList<>(path)); return; } for (int i = 0; i < nums.length; ++i) { if (!used[i]) { used[i] = true; path.add(nums[i]); backtrack(nums, path, used); path.remove(path.size() - 1); // 回退 used[i] = false; } } } public static void main(String[] args) { Permutation p = new Permutation(); int[] nums = {1, 2, 3}; System.out.println(p.permute(nums)); } } ``` 以上两种语言版本均采用了类似的思路,利用递归来完成对解空间的穷举搜索[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值