大家都有个抢红包经历吧,还是一件蛮好玩的事。红包金额总是能分完,而且每个人获得的金额都是随机的,那么其中的算法思路是怎样的呢?来看看吧
思路
1.首先我们要知道红包的总金额大小和红包分发的个数,要随机分完,而且每份加起来要等于总金额,于是可以这样假设这样一个场景:把红包总金额想象成一根线段,将这根线段随机切成5份,每一次都是随机切,每根线段长度加起来等于总长度,这样是不是还原了抢红包的场景啦。

切割算法.png
落实代码
const num = 100; //总金额
const peopel = 5;
/**
* 获取 n-1 个切割点
* @param {*} n
*/
function getCut(n){
let arr = [];
for (let i = 1; i <= n - 1; i++) {
const result = (Math.random()*(num-1))+1;
arr.push(result);
}
return arr;
}
/**
* 冒泡排序算法
* @param {*} arr
*/
function mpSort(arr){
for (let i = 1; i < arr.length; i++) {
// 第i次排序
for (let j = 0; j < arr.length - i; j++) {
// 比较 j 和 j+1 两个位置的数字
if (arr[j] > arr[j + 1]) {
//交换
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr
}
const cutting = mpSort(getCut(peopel)); //将获取到的切割点从小到大排序
let newArr = new Array(peopel) //定义一个n个人红包金额数组(比切割点多一个)
/**
* 分发红包
* @param {*} cutting 升序排序的切割点数组
* @param {*} newArr 红包数组
*/
function distribution(cutting,newArr){
for (let k = 0; k < cutting.length + 1; k++) {
if(k == 0){
newArr[k] = cutting[k]
continue;
}
if(k == cutting.length){
newArr[k] = num - cutting[k - 1]
break;
}
newArr[k] = cutting[k] - cutting[k - 1]
}
return newArr;
}
console.log(distribution(cutting,newArr))
要记得保留小数位。
结尾
最后小伙伴们肯定发现了问题吧,下面的问题就留给你们思考哦~
1.切割点重复或者两点之间的差小于0.01了,这样就不符合我们平时抢红包最少都抢得到0.01元了。
2.如何尽可能降低时间复杂度和空间复杂度。

略略略.gif
感谢浏览