紅包算法

原文:https://crossoverjie.top/JCSprout/#/algorithm/common-algorithm?id=%E7%BA%A2%E5%8C%85%E7%AE%97%E6%B3%95-1java

 

 

import java.util.LinkedList;
import java.util.List;

public class RedPacket {

    /**
     * 生成紅包最小值 1分
     */
    private static final int MIN_MONEY = 1;

    /**
     * 生成紅包最大值 200人民幣
     */
    private static final int MAX_MONEY = 200 * 100;

    /**
     * 小於最小值
     */
    private static final int LESS = -1;
    /**
     * 大於最大值
     */
    private static final int MORE = -2;

    /**
     * 正常值
     */
    private static final int OK = 1;

    /**
     * 最大的紅包是平均值的 TIMES 倍,防止某一次分配紅包較大
     */
    private static final double TIMES = 2.1F;

    private int recursiveCount = 0;

    public List<Integer> splitRedPacket(int money, int count) {
        List<Integer> moneys = new LinkedList<>();

        //金額檢查,若是最大紅包 * 個數 < 總金額;則須要調大最小紅包 MAX_MONEY
        if (MAX_MONEY * count < money) {
            System.err.println("請調大最小紅包金額 MAX_MONEY=[" + MAX_MONEY + "]");
            return moneys ;
        }


        //計算出最大紅包
        int max = (int) ((money / count) * TIMES);
        max = max > MAX_MONEY ? MAX_MONEY : max;

        for (int i = 0; i < count; i++) {
            //隨機獲取紅包
            int redPacket = randomRedPacket(money, MIN_MONEY, max, count - i);
            moneys.add(redPacket);
            //總金額每次減小
            money -= redPacket;
        }

        return moneys;
    }

    private int randomRedPacket(int totalMoney, int minMoney, int maxMoney, int count) {
        //只有一個紅包直接返回
        if (count == 1) {
            return totalMoney;
        }

        if (minMoney == maxMoney) {
            return minMoney;
        }

        //若是最大金額大於了剩餘金額 則用剩餘金額 由於這個 money 每分配一次都會減少
        maxMoney = maxMoney > totalMoney ? totalMoney : maxMoney;

        //在 minMoney到maxMoney 生成一個隨機紅包
        int redPacket = (int) (Math.random() * (maxMoney - minMoney) + minMoney);

        int lastMoney = totalMoney - redPacket;

        int status = checkMoney(lastMoney, count - 1);

        //正常金額
        if (OK == status) {
            return redPacket;
        }

        //若是生成的金額不合法 則遞歸從新生成
        if (LESS == status) {
            recursiveCount++;
            System.out.println("recursiveCount==" + recursiveCount);
            return randomRedPacket(totalMoney, minMoney, redPacket, count);
        }

        if (MORE == status) {
            recursiveCount++;
            System.out.println("recursiveCount===" + recursiveCount);
            return randomRedPacket(totalMoney, redPacket, maxMoney, count);
        }

        return redPacket;
    }

    /**
     * 校驗剩餘的金額的平均值是否在 最小值和最大值這個範圍內
     *
     * @param lastMoney
     * @param count
     * @return
     */
    private int checkMoney(int lastMoney, int count) {
        double avg = lastMoney / count;
        if (avg < MIN_MONEY) {
            return LESS;
        }

        if (avg > MAX_MONEY) {
            return MORE;
        }

        return OK;
    }


    public static void main(String[] args) {
        RedPacket redPacket = new RedPacket();
        List<Integer> redPackets = redPacket.splitRedPacket(100*100, 2);
        System.out.println(redPackets);

        int sum = 0;
        for (Integer red : redPackets) {
            sum += red;
        }
        System.out.println(sum);
    }

}
相關文章
相關標籤/搜索