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

来源:互联网 发布:c语言 表达式的值 编辑:程序博客网 时间:2024/06/05 18:33

今天在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

原创粉丝点击