【Java/算法/排列】ABCDE共5人站成一排,如果B必须站在A的右边(AB不必相邻),那么不同的排法有几种,请列举出来。

【数学解法一】

可以预设A的位置进行分类讨论:

如果A在右一,如_ _ _ _ A,那么B没地方站,这种情况排法为0;

如果A在右二,如_ _ _ A _,那么B只有1个地方可选,如_ _ _ A B,其余CDE全排,这种情况排法为A33;

如果A在正中,如_ _ A _ _,那么B有2个地方可选,其余CDE全排,这种情况排法为C21A33;

如果A在左二,如_ A _ _ _,那么B有3个地方可选,其余CDE全排,这种情况排法为C31A33;

如果A在左一,如A _ _ _ _,那么B有4个地方可选,其余CDE全排,这种情况排法为C41A33;

以上五类累计,sum=(0+1+C21+C31+C41)*A33=10*6=60种

【数学解法二】

五人全排有A55种,B在A的右侧的几率和B在左侧的几率是一样的,所以排法为A55/2=5*4*3*2*1/2=5*4*3=60种

【程序解法】

思路:五人全排,用A下标<B小标当过滤器,筛完即可。

ARightB类:

package test230426;

import java.util.List;

import arrange.Arranger;

/**
 * ABCDE共5人站成一排,如果B必须站在A的右边(AB不必相邻),那么不同的排法有几种,请列举出来。
 */
public class ARightB {
    public static void main(String[] args) {
        final String[] names = { "A","B", "C", "D", "E" };
        final int[] arr = { 0, 1, 2, 3,4 };

        Arranger arranger = new Arranger(arr);
        int idx = 0;
        for (List<Integer> res : arranger.getResults()) {
            int posA=-1;
            int posB=-1;
            
            for(int j=0;j<res.size();j++) {
                int val=res.get(j);
                if(val==0) {
                    posA=j;
                }
                if(val==1) {
                    posB=j;
                }
            }
            
            if(posA<posB) {
                String name = "";
                for (int i = 0; i < names.length; i++) {
                    name += names[res.get(i)];
                }

                System.out.println(String.format("%02d", ++idx) + "." + name);
            }
        }
    }
}

Arranger类:

package arrange;

import java.util.ArrayList;
import java.util.List;

/**
 * 用于产生数组全排列结果的工具类
 * @since 2023/4/21
 */
public class Arranger {
    // 保存在内部的原始元素数组的引用
    private int[] rawArr;

    // 返回结果
    private List<List<Integer>> results;

    /**
     * 构造函数
     * 
     * @param raws 原始元素数组
     */
    public Arranger(int[] raws) {
        rawArr = raws;
        results = new ArrayList<>();

        doArrange(new ArrayList<>());
    }

    /**
     * 使用递归进行全排列,结果放在results中
     * 
     * @param initialList 初始链表
     */
    private void doArrange(List<Integer> initialList) {
        List<Integer> innerList = new ArrayList<>(initialList);

        if (rawArr.length == initialList.size()) {
            results.add(innerList);
        }

        for (int i = 0; i < rawArr.length; i++) {
            if (innerList.contains(rawArr[i])) {
                continue;
            }

            innerList.add(rawArr[i]);
            doArrange(innerList);
            innerList.remove(innerList.size() - 1);
        }
    }

    /**
     * 获得结果链表的引用
     * 
     * @return
     */
    public List<List<Integer>> getResults() {
        return results;
    }

    // 测试
    public static void main(String[] args) {
        int[] numbers = { 1, 2, 3,4,5};
        Arranger arranger = new Arranger(numbers);

        int idx = 0;
        for (List<Integer> re : arranger.getResults()) {
            System.out.println(String.format("%02d", ++idx) + "." + re);
        }
    }
}

【输出】

01.ABCDE
02.ABCED
03.ABDCE
04.ABDEC
05.ABECD
06.ABEDC
07.ACBDE
08.ACBED
09.ACDBE
10.ACDEB
11.ACEBD
12.ACEDB
13.ADBCE
14.ADBEC
15.ADCBE
16.ADCEB
17.ADEBC
18.ADECB
19.AEBCD
20.AEBDC
21.AECBD
22.AECDB
23.AEDBC
24.AEDCB
25.CABDE
26.CABED
27.CADBE
28.CADEB
29.CAEBD
30.CAEDB
31.CDABE
32.CDAEB
33.CDEAB
34.CEABD
35.CEADB
36.CEDAB
37.DABCE
38.DABEC
39.DACBE
40.DACEB
41.DAEBC
42.DAECB
43.DCABE
44.DCAEB
45.DCEAB
46.DEABC
47.DEACB
48.DECAB
49.EABCD
50.EABDC
51.EACBD
52.EACDB
53.EADBC
54.EADCB
55.ECABD
56.ECADB
57.ECDAB
58.EDABC
59.EDACB
60.EDCAB

【结论】

数学两种解法和程序解法都可以相互印证。

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值