【Java/算法/组合】楼梯共有12级台阶,每步可上1级,也可上2级,要用8步走完这12级台阶,问共有多少种不同的走法?并请列举出这些走法

【数学解法】

此题貌似与组合无关,分析后可发现是直接相关的。

设走一级n次,走二级m次,那么有:

n+m=8

n+2m=12

解这个二元一次方程得n=4,m=4.

至此可言,只能走4次二级,4次一级登上这层楼梯。

求不同得走法,就是在8步中,选4次2级(其余全为1级)。

8选4即C84=8*7*6*5/4*3*2*1=2*35=70次

【程序解法】

思路:做一个数组{0,1,2,3,4,5,6,7}进行8选4,选出4个元素作为下标,把数组{"1","1","1","1","1","1","1","1"}中得对应项置为2,此即走法。

比如说,{0,1,2,3,4,5,6,7}进行8选4后得到[0,1,2,3],那么{"1","1","1","1","1","1","1","1"}将变成{"2","2","2","2","1","1","1","1"},这就是这一步对应的走法。

Footstep类:

package test230426;

import java.util.List;

import test230425.Combination;

/**
 * 楼梯共有12级台阶,每步可上1级,也可上2级,要用8步走完这12级台阶,问共有多少种不同的走法?并请列举出这些走法
 */
public class Footstep {
    public static void main(String[] args) {
        final int[] arr= {0,1,2,3,4,5,6,7};
        Combination c=new Combination(arr,4);
        List<List<Integer>> results=c.getResults();
        
        int idx=0;
        for(List<Integer> res:results) {
            String[] steps= {"1","1","1","1","1","1","1","1"};
            
            for(int i:res) {
                steps[i]="2";
            }
            
            String str=String.join(",", steps);
            
            System.out.println(String.format("%02d", ++idx) +"."+str);
        }
    }
}

Combination类:

package test230425;

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

/**
 * 数学中排列组合中的组合器实现
 * 
 */
public class Combination {
    /**
     * 用于存放中间结果
     */
    private Stack<Integer> stack;
    
    /**
     * 用于存放结果
     */
    private List<List<Integer>> results;
    
    /**
     * 构造函数
     * @param arr 进行组合的元素
     * @param count 选多少个
     */
    public Combination(int[] arr,int count) {
        if(count>arr.length) {
            throw new ArrayIndexOutOfBoundsException(count+">"+arr.length);
        }
        
        stack = new Stack<>();
        results=new ArrayList<>();
        doSelect(arr,count,0,0);
    }
    
    /**
     * 进行选择
     * @param arr 目标数组
     * @param expect 期望选择数量
     * @param actual 实际选择数量
     * @param current 当前下标
     */
    private void doSelect(int[] arr, int expect, int actual, int current) {
        if(actual == expect) {
            List<Integer> list=new ArrayList<>();
            
            for(int i:stack) {
                list.add(i);
            }
            
            results.add(list);
            
            return;
        }
         
        for(int i=current;i<arr.length;i++) {
            if(!stack.contains(arr[i])) {
                stack.add(arr[i]);
                doSelect(arr, expect, actual+1, i);
                stack.pop();
            }
        }
    }
    
    /**
     * 取得组合结果
     * @return
     */
    public List<List<Integer>> getResults(){
        return results;
    }
    
    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        final int[] arr= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30};
        final int count=2;
        
        Combination c=new Combination(arr,count);
        List<List<Integer>> results=c.getResults();
        
        int idx=0;
        for(List<Integer> res:results) {
            System.out.println(String.format("%02d", ++idx) +"."+res);
        }
    }
}

【输出】

01.2,2,2,2,1,1,1,1
02.2,2,2,1,2,1,1,1
03.2,2,2,1,1,2,1,1
04.2,2,2,1,1,1,2,1
05.2,2,2,1,1,1,1,2
06.2,2,1,2,2,1,1,1
07.2,2,1,2,1,2,1,1
08.2,2,1,2,1,1,2,1
09.2,2,1,2,1,1,1,2
10.2,2,1,1,2,2,1,1
11.2,2,1,1,2,1,2,1
12.2,2,1,1,2,1,1,2
13.2,2,1,1,1,2,2,1
14.2,2,1,1,1,2,1,2
15.2,2,1,1,1,1,2,2
16.2,1,2,2,2,1,1,1
17.2,1,2,2,1,2,1,1
18.2,1,2,2,1,1,2,1
19.2,1,2,2,1,1,1,2
20.2,1,2,1,2,2,1,1
21.2,1,2,1,2,1,2,1
22.2,1,2,1,2,1,1,2
23.2,1,2,1,1,2,2,1
24.2,1,2,1,1,2,1,2
25.2,1,2,1,1,1,2,2
26.2,1,1,2,2,2,1,1
27.2,1,1,2,2,1,2,1
28.2,1,1,2,2,1,1,2
29.2,1,1,2,1,2,2,1
30.2,1,1,2,1,2,1,2
31.2,1,1,2,1,1,2,2
32.2,1,1,1,2,2,2,1
33.2,1,1,1,2,2,1,2
34.2,1,1,1,2,1,2,2
35.2,1,1,1,1,2,2,2
36.1,2,2,2,2,1,1,1
37.1,2,2,2,1,2,1,1
38.1,2,2,2,1,1,2,1
39.1,2,2,2,1,1,1,2
40.1,2,2,1,2,2,1,1
41.1,2,2,1,2,1,2,1
42.1,2,2,1,2,1,1,2
43.1,2,2,1,1,2,2,1
44.1,2,2,1,1,2,1,2
45.1,2,2,1,1,1,2,2
46.1,2,1,2,2,2,1,1
47.1,2,1,2,2,1,2,1
48.1,2,1,2,2,1,1,2
49.1,2,1,2,1,2,2,1
50.1,2,1,2,1,2,1,2
51.1,2,1,2,1,1,2,2
52.1,2,1,1,2,2,2,1
53.1,2,1,1,2,2,1,2
54.1,2,1,1,2,1,2,2
55.1,2,1,1,1,2,2,2
56.1,1,2,2,2,2,1,1
57.1,1,2,2,2,1,2,1
58.1,1,2,2,2,1,1,2
59.1,1,2,2,1,2,2,1
60.1,1,2,2,1,2,1,2
61.1,1,2,2,1,1,2,2
62.1,1,2,1,2,2,2,1
63.1,1,2,1,2,2,1,2
64.1,1,2,1,2,1,2,2
65.1,1,2,1,1,2,2,2
66.1,1,1,2,2,2,2,1
67.1,1,1,2,2,2,1,2
68.1,1,1,2,2,1,2,2
69.1,1,1,2,1,2,2,2
70.1,1,1,1,2,2,2,2

END

posted @ 2023-04-26 16:21  逆火狂飙  阅读(218)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东