过年之抢红包算法

前言

昨天是大年初一,怎么说呢,因为在读大学, 没有出来工作,所以昨晚也是陆陆续续有收到一些红包。然后想起自己对算法感兴趣,以前也看过一些公众号有讲过抢红包算法,今天就更新一遍关于抢红包的算法,对学过数据结构或者对抢红包感兴趣的可以看一看。本文就讲两个抢红包算法。

PS:关于抢红包算法我是参看公众号“程序员小灰”。这个公众号是引领我学数据结构的公众号,通过漫画的形式讲得很通俗易懂。


抢红包算法的要求

假设有10元钱,10个人分:

  • 每个人至少分到0.01元,不可以分到0元
  • 每个人分到的金额加起来要等于10元,不可以多于10元,也不可以少于10元
  • 每个人分的金额要尽可能随机,不能差距太大

抢红包一

当初大二学习数据结构的时候老师就有布置一道作业题说叫我们回去写一个类似于微信的抢红包算法,然后下个星期看哪位同学写得好。所以第一个抢红包算法应该大家很容易理解。

思路

每个人每次抢到的金额范围是:(0,剩余金额)。

不过这个算法思路会违背“每个人分的金额随机,不能差距太大”。

为什么会这样,举个例子:

假设有10元钱,10个人分。

第一个人的随机范围是(0,10),平均分到5元。

假设第一个人随机分到5元,剩余金额为10-5=5元。

第二个人的随机范围是(0,5),平均分到2.5元。

假设第二个人随机分到2.5元,剩余金额为5-2.5=2.5元。

第三个人的随机范围是(0,2.5),平均分到1.25元

以此类推,每一次随机范围越来越小,违背了“每个人分的金额随机,不能差距太大”。

代码

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
package zhihu;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
* @author god-jiang
* @date 2020/1/26 16:49
*/
public class Algorithm {
public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum) {
List<Integer> amountList = new ArrayList<>();
Integer restAmount = totalAmount;
Integer restPeopleNum = totalPeopleNum;
Random random = new Random();
for (int i = 0; i < totalPeopleNum - 1; i++) {
int amount = random.nextInt(restAmount - restPeopleNum - 1) + 1;
restAmount -= amount;
restPeopleNum--;
amountList.add(amount);
}
amountList.add(restAmount);
return amountList;
}

public static void main(String[] args) {
List<Integer> amountList = divideRedPackage(1000, 10);
for (Integer amount : amountList
) {
System.out.println("抢到金额" + new BigDecimal(amount).divide(new BigDecimal(100)));
}
}
}

结果

img


抢红包二

思路

每次抢到的金额=随机范围(0,M/N *2)

M表示剩余红包金额,N表示剩余人数。这个公式保证了每次随机金额的平均值是相等的。

举个例子:

假设有10元钱,10个人分:

10/10 *2=2,所以第一个人分到的范围是(0,2),平均可以分到1元。

假设第一个人随机分到1元,那么剩余金额是10-1=9元。

9/9 *2=2,所以第二个人分到的范围是(0,2),平均可以分到1元。

假设第二个人随机分到1元,那么剩余金额是9-1=8元。

8/8 *2=2,所以第三个人的随机范围也是(0,2),平均可以分到1元。

以此类推,每一次随机范围都是相等的。

代码

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
package zhihu;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
* @author god-jiang
* @date 2020/1/26 15:39
*/
public class Algorithm {
public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum) {
List<Integer> amountList = new ArrayList<>();
Integer restAmount = totalAmount;
Integer restPeopleNum = totalPeopleNum;
Random random = new Random();
for (int i = 0; i < totalPeopleNum - 1; i++) {
//保证金额范围是[1,剩余金额2倍),左闭右开
int amount = random.nextInt(restAmount / restPeopleNum * 2 - 1) + 1;
restAmount -= amount;
restPeopleNum--;
amountList.add(amount);
}
amountList.add(restAmount);
return amountList;
}

public static void main(String[] args) {
List<Integer> amountList = divideRedPackage(1000, 10);
for (Integer amount : amountList
) {
System.out.println("抢到金额" + new BigDecimal(amount).divide(new BigDecimal(100)));
}
}
}

结果

img

总结

抢红包算法就只写了两个,第一个就是以前大二学习数据结构的时候老师布置作业,我的想法就是大概这样,分的不均。第二个算法就是看公众号“程序员小灰”学习到的,很厉害,挺佩服这些大佬的,哈哈。

PS:本文提供的代码红包金额都是以分为单位,因为抢红包最低都是0.01元。

-------------本文结束感谢您的阅读-------------

本文标题:过年之抢红包算法

文章作者:god-jiang

发布时间:2020年01月26日 - 18:24:17

最后更新:2020年01月26日 - 22:50:44

原始链接:https://god-jiang.github.io/2020/01/26/过年之抢红包算法/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

创作不易,您的支持就是我坚持的动力,谢谢大家!
0%