全排列算法本质与实现

本质

解决全排列问题本质是:二分法。
将某个数组的全排列看成是由第0个元素与其后所有元素的全排列组成

做法是每次只需要挑选某个元素作为当前排列的第0个元素,然后剩下的变成子问题递归来解决。

原理

设一个数组的长度为n,则其全排列的个数为n!个。

设f(n)代表对于一个n长度数组的全排列,array(n)代表数组中的第n个元素,+代表拼接。

f(n) = array(1 to n) + f(n - 1)

由此可以看出这个算法需要利用递归来解决问题。每次只需要挑选某个元素作为第0个元素,然后剩下的变成子问题递归来解决。

例子:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]

我们可以从交换的角度和二分(大问题分解成小问题)的角度去思考。我们从交换的角度出发去思考应该如何交换才能形成全排列,从二分的角度思考如何划分子问题。

  1. 对于{1},这个排列只有其本身,于是可以看成自身与自身交换。
  2. 对于{1,2},排列为{{1, 2}, {2, 1}},从分的角度看:可以看成先选出第0个位置应该是哪个数+其后所有数的全排列。二分后就可以将这变成1的情况。
  3. 对于{1, 2, 3},同样是第0个元素可以是1或2或3,然后子问题变成2的情况。

题目

描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

实现

import java.util.ArrayList;
import java.util.TreeSet;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        TreeSet<String> r = new TreeSet<>();
        DFS(r, str.toCharArray(), 0, str.length());
        ArrayList<String> result = new ArrayList<>(r.size());
        for (String s : r) {
            result.add(s);
        }
        return result;
    }
    
    public static void DFS(TreeSet<String> result,char[] str, int begin, int end) {
        if (begin + 1 == end) {
            result.add(new String(str));
        }
        
        for (int i = begin; i < end; i++) {
            swap(str, begin, i);
            
            DFS(result, str, begin + 1, end);
            
            swap(str, begin, i);
        }
    }
    
    public static void swap(char[] array, int aPos, int bPos) {
        char t = array[aPos];
        array[aPos] = array[bPos];
        array[bPos] = t;
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值