常用算法

红包算法

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
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(20000, 100);
System.out.println(redPackets);

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

}

####

1
2


文章作者: gqsu
文章链接: http://www.ipdax.com/2019/01/28/util-常用算法/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 技术笔记分享
支付宝打赏
微信打赏