排列组合问题

来源:互联网 发布:淘宝纪念币是真的吗 编辑:程序博客网 时间:2024/05/29 06:45

排列就不说了,直接上组合问题
组合问题
问题描述:
* 输入n个数,从中选出m个数可构成集合,输出所有这样的集合。
* 输入样例:
* 4 3
* 1 2 3 4
* 输出样例:
* 1 2 3
* 1 2 4
* 1 3 4
* 2 3 4
代码如下所示

import java.util.Scanner;public class Main4 {    static final int MAX_N = 10;    static int n, m;// 从n个数中选出m个数构成组合    static int rcd[] = new int[MAX_N];    static int num[] = new int[MAX_N];// 存放输入的N个数    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);         n = sc.nextInt();         m = sc.nextInt();        for (int i = 0; i < n; i++) {            num[i] = sc.nextInt();        }        select_combination(0, 0);    }    private static void select_combination(int l, int p) {        if (l == m) {// 若选出了m个数,则打印            for (int j = 0; j < m; j++) {                System.out.print(rcd[j]);                if (j < m - 1) {                    System.out.print(" ");                }            }            System.out.println();            return;        }        for (int i = p; i < n; i++) {//上个位置填写的是num[p-1],本次从num[p]开始            rcd[l] = num[i];//在l位置上放该数            select_combination(l + 1, i + 1);//填写下一个位置        }    }}因为在组合生成过程中引入了变量 p,保证了每次填入的数字在num中的下标是递增的,所以不需要使用used进行标记,共C(n, m)种组合。

另一个问题是: 全组合
输入n个数,求这n个数构成的集合的所有子集。
* 输入样例:
* 3
* 1 2 3
* 输出样例:
* 1
* 1 2
* 1 2 3
* 1 3
* 2
* 2 3
* 3
上代码

import java.util.Scanner;public class Main5 {    static final int MAX_N = 10;    static int n, m;    static int rcd[] = new int[MAX_N];    static int num[] = new int[MAX_N];// 存放输入的N个数    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        n = sc.nextInt();        for (int i = 0; i < n; i++) {            num[i] = sc.nextInt();        }        select_combination(0, 0);    }    private static void select_combination(int l, int p) {        for (int j = 0; j < l; j++) {//只需要每次进入递归函数都输出就好了            System.out.print(rcd[j]);            if (j < l- 1) {                System.out.print(" ");            }        }        System.out.println();        for (int i = p; i < n; i++) {// 上个位置填写的是num[p-1],本次从num[p]开始            rcd[l] = num[i];// 在l位置上放该数            select_combination(l + 1, i + 1);// 填写下一个位置        }    }}全组合,共2^n种,包含空集和自身。与全排列一样,若输入的n个数有重复, 那么在输出的2^n种组合中,必然存在重复的项。避免重复的方法与不重复排列算法中使用的类似。

不重复组合
输入n个数,求这n个数构成的集合的所有子集,不允许输出重复的项。
* 输入样例:
* 3
* 1 1 3
* 输出样例:
* 1
* 1 1
* 1 1 3
* 1 3
* 3
上代码

import java.util.Scanner;//不重复组合public class Main6 {    static final int MAX_N = 10;    static int n, m;// 共有n个数,其中本质互不相同的有m个    static int rcd[] = new int[MAX_N];// 每个位置填写的数    static int used[] = new int[MAX_N];// 标记m个数可以使用的次数    static int num[] = new int[MAX_N];   //存放输入中本质不同的m个数    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        n = sc.nextInt();        m = 0;        for (int i = 0; i < n; i++) {            int val = sc.nextInt();            int j = 0;            for (j = 0; j < m; j++) {                if (num[j] == val) {                    used[j]++;                    break;                }            }            if (j == m) {                num[m] = val;                used[m++] = 1;            }        }        unrepeat_conbination(0, 0);    }    private static void unrepeat_conbination(int l, int p) {        int i;        for (i = 0; i < l; i++) {//每次都输出            System.out.print(rcd[i] + " ");        }        System.out.println();         for ( i = p; i <m; i++) {//循环依旧从p开始,枚举剩下的本质不同的数            if (used[i]>0) {//若还可以用,则可用次数减                used[i]--;                rcd[l]=num[i];//在l位置上放该数                unrepeat_conbination(l+1, i);//填写下一个位置                used[i]++;//恢复可用次数            }        }    }}**需要注意的是递归调用时,第二个参数是i,不再是全组合中的i+1!**
0 0
原创粉丝点击