[一天一项目] 获取m个数中和等与k的n个数

今天在CSDN问答看到一个关于递归算法的求值题。觉得很有意思。现在把题目和我自己的答案写下来。

有m个数(有重复值),如果其中的n(n不固定,即可设定)个数的值为k(可设定,不固定)。那么这样的n组合有哪些?

package com.project.GetNNumCount;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class getNNumCount {
    private static int NUM = 0;
    private static int count = 0;

    //因为项目中存在重复数据,所以没有办法用set存储,导致最后生成的list会出现重复数据
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入X个数,用逗号分割:");
        String str = input.nextLine();
        String[] datas = str.split(",");
        System.out.println("请输入数字M:");
        NUM = input.nextInt();
        System.out.println("请输入数字N:");
        count = input.nextInt();
        if (NUM > datas.length) {
            System.out.println("输入的Y必须小于等于X!");
            return;
        }
        combine(Arrays.asList(datas));
    }

    private static void combine(List<String> datas) {
        List<String> list = new ArrayList<String>();
        String tmp;
        //对初始数组进行排序,为后续结果集筛选做准备 
        /**
         *  排序前后差别   
         *  排序前:比如   1,3,1,3   2个数相加 得到 4   
         *  有[1,3],[1,3],[3,1],[3,1],[1,3]几种可能
         *  排序后:1,1,3,3 有[1,3],[1,3],[1,3],[1,3]几种可能
         *  对后面的重复list判断帮助很大
         *  
         */
        for (int i = 0; i < datas.size() - 1; i++) {  
             for (int j = 1; j < datas.size() - i; j++) {  
                int data_1 =Integer.parseInt(datas.get(j));
                int data_2 =Integer.parseInt(datas.get(j-1));
                if (data_2 > data_1) {  
                    tmp = datas.get(j);
                    datas.set(j,datas.get(j-1));
                    datas.set(j-1,tmp); 
                } 
             }
        }   
        for(String str : datas) {
            list.add(str);
            //查看排序后的值
            //System.out.println(str);
        }

        ArrayList<List<String>> subset = getSubset(list);

       getNumCount(subset,count);
    }

    public static String[] getBinaryValue(List<String> datas) {
        int size = datas.size();
        int m = (int) Math.pow(2, size) - 1;
        String[] result = new String[m + 1];
        for (int i = m; i > -1; i--) {
            StringBuffer sb = new StringBuffer(Integer.toBinaryString(i));
            int length = sb.length();
            if (length < size) {
                for (int j = 0; j < size - length; j++) {
                    sb.insert(0, "0");
                }
            }
            result[i] = sb.toString();
        }
        return result;
    }

    public static ArrayList<List<String>> getSubset(List<String> datas) {
        ArrayList<List<String>> result = new ArrayList<List<String>>();
        String[] items = new String[datas.size()];
        int i = 0;
        for (String item : datas) {
            items[i++] = item;
        }
        String[] binaryValue = getBinaryValue(datas);
        for (int j = 0; j < binaryValue.length; j++) {
            String value = binaryValue[j];
            List<String> subset = new ArrayList<String>();
            for (int k = 0; k < value.length(); k++) {
                if (value.charAt(k) == '1')
                    subset.add(items[k]);
            }
            if (subset.size() == NUM)
                result.add(subset);
        }

        return result;
    }

    //获取到最后的list,需要进行最后的筛选
    public static void getNumCount(ArrayList<List<String>> subset, int count) {
        int count_new = 0;
        List<List<String>> list = new ArrayList<List<String>>();
        for (List<String> ts : subset) {
            count_new = 0;
            for (String num : ts) {
                count_new += Integer.parseInt(num);
            }
            //判断是否符合所要求的总和
            if (count_new == count) {
                //如果list长度大于0,就开始与后一个list进行比较
                if(list.size() == 0){
                    list.add(ts);   
                }else{
                    //如果两个list内容不相同,就添加到list中
                    if(!list.get(list.size()-1).equals(ts)){
                        list.add(ts);
                    }
                }

            }

        }
        for(List<String> list1 : list){
            System.out.println(list1);  
        }
        System.out.println("break");
    }
}

如果这题不考虑重复数据的话会简单很多,在初始值生成的时候,用set接受排除重复数据影响就行,之后的操作就很简单了。为了重复数据for到快吐了~~很难受。

查了资料这个题可以用递归算法和回溯算法(对此没有研究,所以知其然而不知其所以然)。同样难受

解题方法很多很多,如果你有更多的更好的解决方法,欢迎交流!谢谢
代码合集:https://github.com/FanceTsui/Project.git

——Fance Tsui

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值