一种第N个红包最大实现的方式

一 序

  需求背景:常叫外面的同学对于美团或者饿了么的那种在微信群里分享的,第N个红包最大的领红包的营销模式很熟悉了。

我们有类似的需求,其实N是后台可以配置的。

营销规则有: 预算金额,有个范围。

                      第N个最大,N的范围配置。

                      最大金额:有个配置范围。

                      剩余红包金额:配置范围。

   qa在测试的时候,发现按照平均数,有除不尽的case。需要重试。

思考了一下,换个思路实现拆红包的第N个最大的实现。

二 一种实现方案:

   

import java.util.Arrays;
import java.util.Random;

import com.alibaba.fastjson.JSON;

public class RedPackageTest {
	
    //小包
	private static final int smalllow =2;
	private static final int smallhigh =5;
	//预算
	private static final int[] yusuan ={30,31,32,33,34,35};
	//最大
	private static final int[] maxnum = {6,7,8};
	
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
		//随机取预算
		 int tmp= (int)Math.floor(Math.random()*yusuan.length);
		 int yusuanNum = yusuan[tmp];
		 //随机取最大
		 int maxtmp= (int)Math.floor(Math.random()*maxnum.length);
		 int maxNum = maxnum[maxtmp];
		 
		 //计算可用剩余金额
		 int avlMoney = yusuanNum -maxNum;
		 // 计算红包总数
		 int totalnum= avlMoney/smallhigh+1;
		 
		 System.out.println("yusuan:"+yusuanNum+",max= "+maxNum+":num:"+totalnum);
		 
		
		int[] result = divived(avlMoney,totalnum);
		System.out.println("yusuan:"+yusuanNum+",max= "+maxNum+",other redpackge reslt:"+JSON.toJSONString(result));
		
	}
	
	public static int[] divived(int money, int n) throws InstantiationException, IllegalAccessException{
		
		if(money < n* smalllow|| money> n*smallhigh ){
			System.out.println("超出范围,不能分配");
		}
		 // 创建一个长度等于n的红包数组
        int[] array = new int[n];
        //第一步 每个红包先塞最基础的边界
        Arrays.fill(array,smalllow);
        //金额减去已分配金额
        money -= n*smalllow;
       
    	System.out.println("before first: now left money:"+money+",array:"+JSON.toJSONString(array));
     
        for(int i=0;i<n;i++ ){        
        	 int tmp= Random.class.newInstance().nextInt(smallhigh) ;//随机取
             int tmpnum = tmp<smalllow?smalllow:tmp;  
        	 if( (array[i] + tmpnum)<=smallhigh){
        		 array[i] +=  tmpnum;        	
        		 money -= tmpnum;//金额减去
        	 }
        	 
        	 System.out.println("fisrt reslut:tmpnum:"+tmpnum+",left money:"+money+",array:"+JSON.toJSONString(array));
        }
        System.out.println("before sec :left money:"+money+",array:"+JSON.toJSONString(array));
        //判断剩余未分配的金额是否大于0,分配剩余金额分散开
        int  j=0;
        while (money > 0){        	
        	 if( array[j%n]<smallhigh)
              {
        		 array[j%n] +=  1;     
        		 money = money -1;    
        		  System.out.println("sec : left money:"+money+",array:"+JSON.toJSONString(array));
              }         
            j++;
        }
        
		return array;		
		
	}

}

对于业务规则,要求是不超预算,所以,可以一开始从预算范围随机取数,在确定最大数的数值与范围。

重点看看刨除了最大数之后,剩余的金额如何在分配范围内进行拆分。

思路是:先根据最小值进行初始化,再进行一次遍历,每次随机填充,不超过上限,对于一轮过后,有剩余的金额,再按整数进行拆分。

运行效果:

yusuan:30,max= 6:num:5
before first: now left money:14,array:[2,2,2,2,2]
fisrt reslut:tmpnum:3,left money:11,array:[5,2,2,2,2]
fisrt reslut:tmpnum:4,left money:11,array:[5,2,2,2,2]
fisrt reslut:tmpnum:2,left money:9,array:[5,2,4,2,2]
fisrt reslut:tmpnum:2,left money:7,array:[5,2,4,4,2]
fisrt reslut:tmpnum:3,left money:4,array:[5,2,4,4,5]
before sec :left money:4,array:[5,2,4,4,5]
sec : left money:3,array:[5,3,4,4,5]
sec : left money:2,array:[5,3,5,4,5]
sec : left money:1,array:[5,3,5,5,5]
sec : left money:0,array:[5,4,5,5,5]
yusuan:30,max= 6,other redpackge reslt:[5,4,5,5,5]

这个case:预算取了30,最大红包6, 剩余:24的分为5个,为:5、4、5、5、5。 复合预期。

  抛砖引玉,肯定不是最优的,看看大家有更好的方案可以贴出来。

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值