算法偶记:子集组合(给定一个元素个数为N的集合(其中元素互不相同),在其中选择M个元素组成子集,共有多少种选法。举例:输入[A,B,C] ,M=2,输出[[A,B],[A,C],[B,C]])

1.  给定一个元素个数为N的集合(其中元素互不相同),在其中选择M个元素组成子集,共有多少种选法。举例:输入[A,B,C] ,M=2,输出[[A,B],[A,C],[B,C]]

算法2.0

 public static void main(String[] args) {
        ArrayList resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 1, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 2, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 3, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 4, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 5, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 6, 0);
        System.out.println(resultList);

        resultList = new ArrayList();
        method2(Arrays.asList(1, 2, 3, 4, 5, 6, 7), null, resultList, 7, 0);
        System.out.println(resultList);
    }

    /**
     * @param argsList   参数
     * @param valueList  上一级的值
     * @param resultList 结果集
     * @param m          结果集目标长度
     * @param start      开始索引
     */
    public static void method2(List argsList, List valueList, List<List> resultList, int m, int start) {
        for (int i = start; i < argsList.size(); i++) {
            List list = new ArrayList();
            if (null != valueList) {
                list.addAll(valueList);
            }
            list.add(argsList.get(i));
            if (list.size() == m) {
                resultList.add(list);
                continue;
            }
            method2(argsList, list, resultList, m, ++start);
        }
    }

算法1.0:(错误的)(感谢读客唯丶丶丶:指出)

public static void main(String[] args) {
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 1));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 2));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 3));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 4));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 5));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 6));
        System.out.println(method(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 7));
    }

    public static List<List> method(List argsList, int m) {
        List result = new ArrayList<>();
        for (int i = 0; i < argsList.size(); i++) {
            List arg = new ArrayList<>();
            arg.add(argsList.get(i));
            if (m == 1) {
                // 如果只有1个数字的组合
                result.add(arg);
                continue;
            }
            // j是 第二位数的索引
            int j = i + 1;
            // count 是圈数
            int count = 0;
            // argsList.size() - j + 1 >= m  主要是判断后面的数字还需不需要循环
            // 例子:1 2 3 4 如果我是需要3个数的组合,那你的循环是不会到3的,因为3后面只有4,最多是2个数的组合,只会到2,2后面有3和4,才能符合3个数的组合
            while (argsList.size() - j + 1 >= m) {
                arg = new ArrayList<>();
                arg.add(argsList.get(i));
                int max = i;
                for (int l = 0; arg.size() < m - 1; l++) {
                    // 这里的作用主要是获取最后一位数之前的全部数
                    // 例子 1 2 3 4 5 , 4位数的组合, 我的想法是 先获取 1 2 3 公共的前缀,然后 遍历4和5
                    arg.add(argsList.get(j + l));
                    max = j + l;
                }
                // k 是最后一位数的索引
                int k = max + count + 1;
                while (arg.size() != m) {
                    // 这里就是为了遍历最后一个数字
                    arg.add(argsList.get(k++));
                }
                result.add(arg);
                if (k == argsList.size()) {
                    // 当k等于最后一位数时,说明 已经遍历完了,第二位数字需要跳到下一位,
                    // 例子 1 2 3 4 ,3位数组合,当k等于索引3的时候,说明 123, 124都遍历完了,需要跳到 13开头
                    j++;
                    count = 0;
                    if (m == 2) {
                        break;
                    }
                    continue;
                }
                // 圈数累加
                count++;
            }
        }
        return result;
    }

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值