c++编程 全排列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++编程 全排列相关的知识,希望对你有一定的参考价值。

题目描述
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。

我们假设对于小写字母有'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。

输入
输出只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
输出
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:

已知S = s1s2...sk , T = t1t2...tk,则S < T 等价于,存在p (1 <= p <= k),使得
s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。

样例输入
abc
样例输出
abc
acb
bac
bca
cab
cba

#include<iostream>
using namespace std;
char a[10];
int b[10],n,m;
bool set[10];
void print()

for(int i=0;i<n-1;i++)
cout<<a[b[i]];
cout<<a[b[n-1]]<<endl;

void trydate(int i,int k)

for(int j=k;j<m;j++)

if(set[j]==false)

set[j]=true;
b[i-1]=j;
if(i<=n-1)
trydate(i+1,j+1);
else
print();
set[j]=false;
b[i-1]=0;



int main()

cin>>a;
cin>>n;
m=strlen(a);
for(int i=0;i<10;i++)
b[i]=0;
for(int i=0;i<m;i++)
set[i]=false;
trydate(1,0);
system("pause");
return 0;
参考技术A VC6上测试通过

#include <stdio.h>
#include <memory.H>
int tab[] = 1,1,2,6,24,120,720;
int h[8]= 0;
char out[6000] = 0, *pOut;

int GetSel ( int n )

int i;
int *p;
p = h - 1;
i = 0;
while ( i <= n )

p++;
while ( *p != 0 )
p++;
i++;

return p-h;


int main ( int argc, char *argv[] )

char str[8];
int len, i, iMax, j;

scanf ( "%s", str );
for ( len = 0; str[len] != 0; len++ );
iMax = tab[len]; pOut = out;
for ( i = 0; i < iMax; i++ )

int ii;
ii = i;
for ( j = 0; j < len; j++ )

int tmp,sel;
tmp = len - j - 1;
tmp = tab[tmp];
sel = ii/tmp;
sel = GetSel ( sel );
*pOut++ = str[sel];
h[sel] = 1;
ii %= tmp;

memset ( h, 0, 32 );
*pOut++ = '\n';

*pOut = 0;
printf ( "%s", out );

算法剑指 Offer II 083. 没有重复元素集合的全排列|46. 全排列(java / c / c++ / python / go / rust)

非常感谢你阅读本文~
欢迎【👍点赞】【⭐收藏】【📝评论】~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~


文章目录


剑指 Offer II 083. 没有重复元素集合的全排列|46. 全排列:

给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。

样例 1

输入:
	nums = [1,2,3]

输出:
	[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

样例 2

输入:
	nums = [0,1]

输出:
	[[0,1],[1,0]]

样例 3

输入:
	nums = [1]
	
输出:
	[[1]]

提示

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

分析

  • 这道算法题采用递归,回溯法比较简单,谁要是非要用循环非递归,二当家的佩服。
  • 提示中说每个数字各不相同,那我们全排列就可以考虑成数字所在位置或者说是数组的下标的不同排列,因为数字都不同,所以我们就不必关心每个数字是几了。
  • 可以单开辟空间存储中间排列,这样我们需要能判断某个数字是否被选择过,可以用hash表存储当前排列结果,然后去看是否含有当前数字,但是这样似乎比较低效。
  • 每个位置的数字都不一样,所以我们直接存储一下某个位置的数字是否被使用即可。
  • 可以直接使用一个布尔数组存储访问过的位置,但是提示中说数字个数最多6个,那我们最多用6个二进制位就可以表示所有数字的已使用和未使用,一个 int 型变量足以,我们用这个 int 型变量的二进制位变化,去对应数字的已使用和未使用。
  • 也可以直接在原数组用交换的方式模拟排列,每个数字在所有位置上都排一次不就是全排列吗?先轮着放第一个位置,然后轮着放第二个位置,以此类推。

题解

java

不使用交换的方式

class Solution 
    public List<List<Integer>> permute(int[] nums) 
        List<List<Integer>> ans = new ArrayList<>();
		dfs(nums, new ArrayList<>(nums.length), 0, ans);
		return ans;
	
	
	private void dfs(int[] nums, List<Integer> row, int flag, List<List<Integer>> ans) 
		if (row.size() == nums.length) 
			ans.add(new ArrayList<>(row));
			return;
		
		for (int i = 0; i < nums.length; ++i) 
			if (((flag >> i) & 1) == 0) 
				row.add(nums[i]);
				dfs(nums, row, flag | (1 << i), ans);
				row.remove(row.size() - 1);
			
		
	

使用交换的方式

class Solution 
    public List<List<Integer>> permute(int[] nums) 
        List<List<Integer>> ans = new ArrayList<>();
		backtrack(nums, 0, ans);
		return ans;
	

	private void backtrack(int[] nums, int cur, List<List<Integer>> ans) 
		if (cur == nums.length) 
			ans.add(Arrays.stream(nums).boxed().collect(Collectors.toList()));
			return;
		
		// 当前位置保持不变,接着排下一个
		backtrack(nums, cur + 1, ans);
		// 换后面的某一个到当前位置
		for (int i = cur + 1; i < nums.length; ++i) 
			swap(nums, cur, i);
			backtrack(nums, cur + 1, ans);
			swap(nums, cur, i);
		
	

	private void swap(int[] nums, int a, int b) 
		nums[a] ^= nums[b];
		nums[b] ^= nums[a];
		nums[a] ^= nums[b];
	


c

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
    *returnSize = numsSize;
    for (int i = 2; i < numsSize; ++i) 
        *returnSize *= i;
    

    int **ans = (int **) malloc(sizeof(int *) * (*returnSize));
    *returnColumnSizes = (int *) malloc(sizeof(int) * (*returnSize));
    for (int i = 0; i < *returnSize; ++i) 
        ans[i] = (int *) malloc(sizeof(int) * numsSize);
        (*returnColumnSizes)[i] = numsSize;
    

    int ansSize = 0;

    backtrack(nums, numsSize, 0, ans, &ansSize);

    return ans;


void backtrack(int* nums, int numsSize, int cur, int **ans, int *ansSize) 
    if (cur == numsSize) 
        for (int i = 0; i < numsSize; ++i) 
            ans[*ansSize][i] = nums[i];
        
        *ansSize += 1;
        return;
    
    // 当前位置保持不变,接着排下一个
    backtrack(nums, numsSize, cur + 1, ans, ansSize);
    // 换后面的某一个到当前位置
    for (int i = cur + 1; i < numsSize; ++i) 
        swap(nums, cur, i);
        backtrack(nums, numsSize, cur + 1, ans, ansSize);
        swap(nums, cur, i);
    


void swap(int* nums, int a, int b) 
    nums[a] ^= nums[b];
    nums[b] ^= nums[a];
    nums[a] ^= nums[b];


c++

class Solution 
private:
    void backtrack(vector<int> &nums, int cur, vector<vector<int>> &ans) 
        if (cur == nums.size()) 
            ans.push_back(nums);
            return;
        
        // 当前位置保持不变,接着排下一个
        backtrack(nums, cur + 1, ans);
        // 换后面的某一个到当前位置
        for (int i = cur + 1; i < nums.size(); ++i) 
            swap(nums[cur], nums[i]);
            backtrack(nums, cur + 1, ans);
            swap(nums[cur], nums[i]);
        
    
public:
    vector<vector<int>> permute(vector<int>& nums) 
        vector<vector<int>> ans;

        backtrack(nums, 0, ans);

        return ans;
    
;

python

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        ans = []

        def backtrack(cur: int) -> None:
            if cur == n:
                ans.append(nums[:])
                return
            # 当前位置保持不变,接着排下一个
            backtrack(cur + 1)
            # 换后面的某一个到当前位置
            for i in range(cur + 1, n):
                nums[cur], nums[i] = nums[i], nums[cur]
                backtrack(cur + 1)
                nums[cur], nums[i] = nums[i], nums[cur]

        backtrack(0)
        return ans
        

go

func permute(nums []int) [][]int 
    n := len(nums)
	var ans [][]int

	var backtrack func(cur int)
	backtrack = func(cur int) 
		if cur == n 
			ans = append(ans, append([]int, nums...))
			return
		
		// 当前位置保持不变,接着排下一个
		backtrack(cur + 1)
		// 换后面的某一个到当前位置
		for i := cur + 1; i < n; i++ 
			nums[cur], nums[i] = nums[i], nums[cur]
			backtrack(cur + 1)
			nums[cur], nums[i] = nums[i], nums[cur]
		
	

	backtrack(0)

	return ans


rust

impl Solution 
    pub fn permute(mut nums: Vec<i32>) -> Vec<Vec<i32>> 
        let mut ans = Vec::new();

        Solution::backtrack(&mut nums, 0, &mut ans);

        ans
    

    fn backtrack(nums: &mut Vec<i32>, cur: usize, ans: &mut Vec<Vec<i32>>) 
        if cur == nums.len() 
            ans.push(nums.clone());
            return;
        
        // 当前位置保持不变,接着排下一个
        Solution::backtrack(nums, cur + 1, ans);
        // 换后面的某一个到当前位置
        (cur + 1..nums.len()).for_each(|i| 
            nums.swap(cur, i);
            Solution::backtrack(nums, cur + 1, ans);
            nums.swap(cur, i);
        );
    



原题传送门:https://leetcode-cn.com/problems/VvJkup/

原题传送门:https://leetcode-cn.com/problems/permutations/


以上是关于c++编程 全排列的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL 全排列函数详解

C++四种编程范式及例子

[c++]数组全排列

C++ 全排列函数 nyoj 366

「C++小例子」全排列001

n个整数全排列的递归实现(C++)