算法:递归全排列

原文链接-算法:递归全排列

算法:递归全排列

排列组合是我高中就很头疼的东西,今天在牛客网刷到了全排列的题,硬着脑袋搞懂了。

全排列

比如给定一个数组[a,b,c],需要将其所有的排列方式输出:abc,acb,bac,bca,cab,cba共6种。

分析

没有重复的全排列

很容易就想到,固定开头,剩下的元素再进行全排列,剩下的怎么进行全排列呢,就是再固定剩余的开头,再剩下的全排列。

这就是递归的思想:

  • 必须有可达到的终止条件,否则程序陷入死循环
  • 子问题在规模上比原问题小
  • 子问题可通过再次递归调用求解
  • 子问题的解应能组合成整个问题的解

分解图如下:

[a,b,c]
a[b,c]
b[a,c]
c[a,b]
ab[c]
ac[b]
ba[c]
bc[a]
ca[b]
cb[a]

上图中,开头固定的元素可以看做是从后面的元素中通过替换得来的,比如从a[b,c]到ab[c]可以看做b和它自己替换得来的,从a[b,c]到ac[b]就是c和b替换得来的。同理[a,b,c]到c[a,b]就是a和c替换得来的。

总结一下,全排列就是从第一个元素开始,每一个元素都和以自己为开头的位置和它之后(包括其自身)的元素替换。

有重复值的全排列
[a,b,c,b]
a[b,c,b]
b[a,c,b]
c[a,b,b]
b[a,b,c]
ab[c,b]
ac[b,b]
ab[b,c]
ba[c,b]
bc[a,b]
bb[a,c]
ca[b,b]
cb[a,b]
cb[a,b]

显然,如果按照没有重复元素的方式来全排列,会得到上图的结果,圆形内的会和其他的重复,圆形的应该舍弃掉,他们有一个共同点,即:将要换出来的那个元素,在剩余元素有和它相同的(不唯一),那么就会重复。因此,在元素换位置之前,需要检查它是否需要置换。

import java.util.ArrayList;
public class Permutation {

    public ArrayList<String> re = new ArrayList<>();
    public void swap(char[] l,int i,int j){//置换函数
        char t = l[i];
        l[i] = l[j];
        l[j] = t;
    }

    public boolean isNeedSwap(char[] l,int i, int j){//判断是否需要置换
        for(int k=i;k<j;k++) {
            if (l[k] == l[j]) {
                return false;
            }
        }
        return true;

    }

    public ArrayList<String> Solution(String str) {
        char[] list = str.toCharArray();
        per(list,0,list.length-1);
        this.re.sort(String::compareTo);
        return this.re;
    }


    public void per(char[] list,int start,int end){
        if(start == end ){
            this.re.add(String.valueOf(list));
        }else {
            for (int i=start;i<=end;i++){
                if(isNeedSwap(list,start,i)){
                    swap(list,start,i);//确定一个前缀
                    per(list,start+1,end);
                    swap(list,start,i);//置换回前缀
                }
            }
        }
    }

    public static void main(String[] argv){
        Permutation permutation = new Permutation();
        for(String s:permutation.Solution("abcb")){
            System.out.println(s);
        }

    }
}

发布了4 篇原创文章 · 获赞 0 · 访问量 3161
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览