package core.util; import java.util.Random; public class NumberRandDivideUtils { /** * Randomly split an integer summary into the sum of N integers between min and max, and store the allocation result in array k * Note: The larger the difference between min~max, the easier it is to assign randomly. On the contrary, the smaller the difference, the more difficult the assignment, or even no solution. * eg:min:5,max:8,summary:20, it can be seen that 5 * +5+5+5+5=20, 6+6+8=20, 7+7+6=20, 5+7+8=20, but use random numbers 5~8, maybe * The first time you get 8, the second time you get 8, no matter how you assign it, it can't be 20 int min = 5; int max = 6; int summary =20; * @MODIFY Perfect solution after reducing allocation and overlay allocation */ public static int[] randDivide(int min, int max, int summary) { int maxl = summary% min == 0? summary / min: summary / min + 1; int[] k = new int[maxl]; // l: used to record the last index of the stored value in the array k int l = 0; int total = 0; if (min == max) {// If the two numbers are equal, the constant if (summary % min == 0) { for (int i = 0; i < k.length; i++) { k [i] = min; } } } else { Random rand = new Random(); int remainder; for (int i = 0; i < k.length; i++) { // remainder remainder = summary - total; // If the remainder is between min and max, jump out and directly set k[++l] as the remainder if (remainder >= min && remainder <= max) { k[i] = remainder; break; } else if (remainder < min) { // minimum length of array int minl = summary % max == 0 ? summary / max : summary / max + 1; // if i < minimum array length, reduce allocation if (i < minl) { k[i] = remainder; l = i; randDivideLessenFiller(summary, min, k, l); break; } else {// If i>= minimum array length, do stack allocation randDivideRemainder(summary, max, k, l, remainder); break; } } // Generate a random number between min and max int rd = rand.nextInt(max - min + 1) + min; k[i] = rd; total += rd; l = i; } } // If the sum in the check array is not equal to summary, return 0 int t = 0; for (int i = 0; i < k.length; i++) { t += k[i]; } if (t != summary) { return null; } return k; } private static void randDivideLessenFiller(int summary, int min, int[] k, int l) { if (summary / (l + 1) < min) return; Random rand = new Random(); // a random number between min and mean int rv = rand.nextInt (summary / (l + 1) - min + 1) + min; int r = rv - k[l]; int j = 0; while (r > 0 && j < 1000) { int i = rand.nextInt (l); if (k[i] - r >= min) { k[i] -= r; k[l] += r; break; } int _r = rand.nextInt(r) + 1; k[i] -= _r; k[l] += _r; r -= _r; j++; } } /** * l: the last length of the array r: remainder d: control the depth of random allocation, the value of j is generally less than 1000, to prevent stack overflow caused by no solution */ private static void randDivideRemainder(int summary, int max, int[] k, int l, int r) { if (summary / (l + 1) > max) return; Random rand = new Random(); int j = 0; while (r > 0 && j < 1000) { int i = rand.nextInt (l); if (k[i] + r <= max) { k[i] = k[i] + r; break; } int _tempMax = rand.nextInt(max - summary / (l + 1) + 1) + summary / (l + 1); for (int t = 0; t <= l; t++) { if (k[t] < _tempMax) { // The maximum number is the maximum number of intervals required by the program-k[i], that is, the space is compared with the remainder int _max = (_tempMax - k[t]) < r ? (_tempMax - k[t]) : r; if (_max == 0) continue; // The reason for still using random numbers here instead of auto-padding is to not make the numbers neat int rn = rand.nextInt(_max) + 1; k[t] += rn; r -= rn; } } j++; } } }