简单随机红包生成java实现

问题描述:将固定金额的钱total随机分发给n个人,每个人获得的金额不小于min且最大不超过max?
解题思路:先为每个人分配min元,然后将剩余的钱按[0-(max-min)]的区间随机分配,分配时注意判断余额是否足够,是否超过了max,循环分配多次,直到分完为止。对分配玩后的结果,存在向前倾斜的情况,再采用随机乱序的方法将结果搅乱,便得到最终的结果。以下是代码实现:

package com.hongbao;

import java.util.Random;

public class Hongbao {
    /**
     * MIN:最小值,MAX:最大值,TOTAL:总金额,N:人数
     */
    private static int MIN=6,MAX=12,TOTAL=100,N=10;

    /****概率统计/均值计算*/
    public static void main(String []ww){
        int []arr=test();
        int i=0;
        for(;i<1000;i++){
            int []arr1=test();
            for(int j=0;j<arr.length;j++){//搜集数据,计算分布情况
                arr[j]=arr[j]+arr1[j];
            }
        }
        System.out.println();
        for(int item:arr){
            int avg=item/(i+1);
            System.out.print(item+"("+avg+")"+" ");//输出每个人获得的钱数的平均值,以观察分配是否随机
        }
        //904(8) 928(9) 958(9) 966(9) 1003(9) 994(9) 1086(10) 1071(10) 1097(10) 1093(10) 
        //从计算的结果来看,概率向后倾斜,也就是后面获得大红包的几率比前面大

        //加随机乱序后的结果
        //1027(10) 1029(10) 1020(10) 1009(9) 991(9) 983(9) 987(9) 1032(10) 1010(10) 1012(10) 
        //1021(10) 1011(10) 1022(10) 1019(10) 995(9) 1000(9) 1004(9) 988(9) 1017(10) 1023(10) 
        //993(9) 1031(10) 1052(10) 1021(10) 1009(9) 984(9) 985(9) 1013(10) 1011(10) 1001(9) 
        //1032(10) 994(9) 1013(10) 1016(10) 1008(9) 1023(10) 1016(10) 1007(9) 972(9) 1019(10) 
    }
    /****测试**/
    public static int[] test(){
        int min=MIN,max=MAX,total=TOTAL,n=N;
        int []arr=hb(n,total,min,max);
        int sum=0;
        for(int item:arr){
            sum+=item;
            System.out.print(" "+item);
        }
        System.out.println("\n总:"+sum);
        return arr;
    }
    /**
     * 对随机分配后的结果进行乱序处理
     * @param arr
     * @return
     */
    public static int[] disorder(int []arr){
        Random rd=new Random();
        int temp=0;
        for(int i=0;i<arr.length;i++){
            int index=rd.nextInt(arr.length);
            if(index!=i){
                temp=arr[index];
                arr[index]=arr[i];
                arr[i]=temp;
            }
        }
        return arr;
    }
    /**
     * 根据设定的参数,返回分配后的结果
     * @param n
     * @param total
     * @param min
     * @param max
     * @return
     */
    public static int[] hb(int n,int total,int min,int max){
        //先校验数据
        int [] arr=new int[n];
        if(n*min>total||n*max<total){
            System.out.println("错误的金额上下限");
            return null;
        }
        for(int i=0;i<n;i++){//先根据最低金额分配
            arr[i]=min;//保底
        }
        int surplus=total-n*min;//计算余额
        int iter=0;
        while(true){//根据余额随机分配,直到余额全部分完
            iter++;
            surplus=fenpei(arr,min,max,surplus);
            if(surplus<=0){
                System.out.println("迭代次数:"+iter);
                break;
            }
        }
        return disorder(arr);
    }

    /**
     * 将余额平均分到数组中
     * @param arr 待分配对象集合
     * @param min 最小金额
     * @param max 最大金额
     * @param total 总金额(余额)
     * @param f true:正序分配,false:倒序分配
     * @return 余额
     */
    public static int fenpei(int []arr,int min,int max,int total){
        int surplus=total;
        if(surplus<=0)return 0;
        Random rd=new Random();
        int right=max-min+1;//计算可分配的金额上限
        for(int i=0;i<arr.length;i++){
            int r=rd.nextInt(right);//获取一个随机数
            int value=arr[i];
            if(value+r>max){//若超出,则取最大值
                r=max-value;
            }
            if(surplus<=r)r=surplus;//余额不够时,直接取余额
            value=value+r;
            arr[i]=value;//分配金额
            surplus=surplus-r;//重新计算余额
            if(surplus<=0){
                break;
            }
        }
        return surplus;
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾生有牙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值