At first, I thought it should be random every time I grab a red envelope. The random upper limit is the amount of the remaining red envelopes. This is problematic. For example, if I send a red envelope of 100 yuan, the first person's random range is (0,100), and the average can grab 50 yuan.Then the second person's red envelope (0,50 yuan) can grab 25 yuan on average. Obviously, everyone's chances are different, and the latter people suffer more.
First look at the test: Notice the amount, this is an optimized algorithm, not as simple as throwing a random number directly above. The following algorithm works equally well
/**
*
* @param number
* @param total
* @param min
* @return
*/
public static List getRed(int number,float total,double min){
float money;
double max;
int i = 1;
List<Float> math = new ArrayList();
DecimalFormat df = new DecimalFormat("###.##");
while (i < number) {
//Ensure that even if one red packet is the largest, the remaining red packets will not be less than the minimum
max = total - min * (number - i);
int k = (int)(number - i) / 2;
//Make sure the last two people don't carry more red bags than the rest
if (number - i <= 2) {
k = number - i;
}
//Maximum Red Packet Limited Average Up and Down
max = max / k;
//Ensure that each red packet is greater than the minimum and not greater than the maximum
money = (int) (min * 100 + Math.random() * (max * 100 - min * 100 + 1));
money = (float)money / 100;
//Keep two decimal places
money = Float.parseFloat(df.format(money));
total=(int)(total*100 - money*100);
total = total/100;
math.add(money);
System.out.println("No." + i + "Personal get" + money + "Be left over" + total);
i++;
//The last person takes the rest of the red bag
if (i == number) {
math.add(total);
System.out.println("No." + i + "Personal get" + total + "0 remaining");
}
}
//Index of the largest value in the array
System.out.println("No. 1 in this red envelope" + (math.indexOf(Collections.max(math)) + 1) + "Personal best hand");
return math;
}
Look at the second test: The amount seized each time = random interval (0, M / N X 2)
Suppose there are 10 people and the total amount of red envelope is 100 yuan.100/10X2 = 20, so the first person's random range is (0, 20), which averages 10 yuan.Assuming that the first person is randomly assigned to 10 yuan, the remaining amount is 100-10 = 90 yuan.90/9X2 = 20, so the second person's random range is also (0, 20), averaging 10 yuan.
/**
* Can guarantee the same probability
* @param totalMoney
* @param totalPeople
* @return
*/
private static List<Float> divideRedPackage(Integer totalMoney,Integer totalPeople){
List<Float> allList = new ArrayList<>();
DecimalFormat df = new DecimalFormat("###.##");
Float restAmount = Float.valueOf(totalMoney);
Integer restPeople = totalPeople;
Random random = new Random();
Float tempAmount;
for (int i = 0;i < totalPeople-1;i++){
tempAmount = Float.valueOf(random.nextInt((int) (restAmount/restPeople * 2)) + 1);
tempAmount = Float.parseFloat(df.format(tempAmount));
restAmount -= tempAmount;
restPeople--;
allList.add(tempAmount);
System.out.println("No." + (i+1) + "Personal get" + tempAmount + "Be left over" + restAmount);
}
allList.add(restAmount);
System.out.println("No." + totalPeople + "Personal get" + restAmount);
return allList;
}
How to choose depends on the specific needs, I believe it will be used!!!