Randomly split an integer S into the sum of integers between min and max, and store the allocation result in array K [revised version]

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++;
		}
	}
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326471496&siteId=291194637