Java递归实现数学中的排列问题

1.代码实现

package main.java.ClassicalAlgorithm;

import java.util.*;

/**
 * @auther 1taoliu
 * @date 2021/3/8 上午10:48
 */
public class Permutation {

    public static List<List<Integer>> list = new ArrayList<>();

    public static void main(String[] args) {
        fullPerm(new int[] {1,2,3,4},new Stack<Integer>());
        //cPerm(new int[]{1,2,3,4,5},5,3,new Stack<Integer>());
        for (List<Integer> list1:list){
            System.out.println(list1);
        }
    }


    /**
     * 全排列
     *
     * @param array 数组
     * @param stack 排列结果
     */
    public static void fullPerm(int[] array, Stack<Integer> stack) {
        //递归出口
        if (array.length <= 0) {
            //添加结果
            List<Integer> listTemp = new ArrayList<>();
            for (int i : stack) {
                listTemp.add(i);
            }
            list.add(listTemp);
        } else {
            for (int i = 0; i < array.length; i++) {
                int[] temp = new int[array.length - 1];
                //将索引为i左侧的数据添加进数组
                System.arraycopy(array, 0, temp, 0, i);
                //将索引为i右侧的数据添加进数组
                System.arraycopy(array, i + 1, temp, i, array.length - i - 1);
                //将索引为i的数据添加进结果
                stack.push(array[i]);
                //递归调用
                fullPerm(temp, stack);
                //移除上一次添加进去的数据
                stack.pop();
            }
        }
    }


    /**
     * @param array 待排列数据
     * @param n     n个数
     * @param m     m个数
     * @param stack 选取的m-1个数据
     */
    public static void cPerm(int[] array,int n,int m,Stack<Integer> stack){
        if (m==1){
            for (int i:array){
                List<Integer> listTemp = new ArrayList<>();
                for (int j:stack){
                    listTemp.add(j);
                }
                listTemp.add(i);
                list.add(listTemp);
            }
        }
        for (int i = 0; i < n; i++) {
            stack.push(array[i]);
            int[] temp = new int[array.length - 1];
            //将索引为i左侧的数据添加进数组
            System.arraycopy(array, 0, temp, 0, i);
            //将索引为i右侧的数据添加进数组
            System.arraycopy(array, i + 1, temp, i, array.length - i - 1);
            //递归调用
            cPerm(temp,n-1,m-1,stack);
            stack.pop();
        }
    }
}

2.核心思想

全排列:每次从数组中选取一个数,并把这个数字移出数组,并递归调用以缩小数组范围,当数组长度为0时,跳出当前递归。
选择排列:n选m,在全排列当基础上进行适当改动,分解问题,如5选3 --> 4选2 --> 3选1,将已有的m-1个数据与剩余的n+1-m分别组合即可获得最终结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值