正整数拆分算法

144 阅读1分钟

需求背景 :将一个正整数 L 拆分成 n 个正整数,最大值不超过 t 的算法

public class RandomInteger {
    public static void main(String[] args) {
        int n = 10;
        int L = 200;
        int t = 88;
        for (int i = 0; i < 20; i++) {
            List<Integer> list = new ArrayList<>();
            test(list, n, L, t);
            System.out.println("数量: " + list.size());
            int sum = list.stream().mapToInt(Integer::intValue).sum();
            int max = list.stream().mapToInt(Integer::intValue).max().getAsInt();
            //验证一下结果
            System.out.println(list.toString()); 
           System.out.println("total:======>" + sum + " max ======>" + max + " size:=======> " + list.size());
        }
    }
    public static void test(List<Integer> list, int n, int L, int t) {
        List<Integer> result = random(n, L);
        int sum = result.stream().mapToInt(Integer::intValue).sum();
        int max = result.stream().mapToInt(Integer::intValue).max().getAsInt();
        if (sum == L && result.size() == n && max > t) {
            test(list, n, L, t);
        } else {
            list.addAll(result);
        }
    }
    /**
     * @param n 数量
     * @param L 数字
     */
    public static List<Integer> random(int n, int L) {
        Random rand = new Random();
        List<Integer> result = new ArrayList<>();
        List<Integer> ns = new ArrayList<>();
        //先随机取n次
        for (int i = 0; i < n; i++) {
            ns.add(rand.nextInt(L));
        }
        //从小到大排序
        Collections.sort(ns);
        int step_num = 0;
        //每次随机出来的数
        int num_area = 0;
        //数字区间
        for (int j = 0; j < n; j++) {
            if (j + 1 == n) {
                //最后一个就不用算了
                result.add(L - step_num);
                break;
            }
            num_area = ns.get(j) - step_num;
            //每次从这个区间里面取随机数
            int num = num_area == 0 ? 0 : rand.nextInt(num_area); 
            step_num += num;
            result.add(num);
        }
        return result;
    }
}