-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathRedPacket.java
More file actions
138 lines (107 loc) · 3.57 KB
/
RedPacket.java
File metadata and controls
138 lines (107 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package com.haobin.algorithm;
import java.util.LinkedList;
import java.util.List;
/**
* @Author HaoBin
* @Create 2020/4/26 11:47
* @Description: 红包算法
* 模拟微信红包算法(金额单位:分)
**/
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 ;
}
//计算出最大红包(平均值的 TIMES 倍)
int max = (int) ((money / count) * TIMES);
max = Math.min(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;
}
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, 10);
System.out.println(redPackets);
int sum = 0;
for (Integer red : redPackets) {
sum += red;
}
System.out.println(sum);
}
}