目前正在撰寫一個程式,該程式可以找到陣列中 3 個給定數字的最佳比率。然而,我目前的代碼只需要 3 個數字,并排列它們以找到最接近 100 的 3 個數字排列。我需要代碼具有適應性,以便它采用 3 個數字并給出最接近 100 的 n 個數字排列。
public static int[] mmru(int[] array) {
int result = 1000;
int[] ideal = new int[0];
int closestResult = 100;
for (int i = 0; i < 3; i ) {
for (int j = 0; j < 3; j ) {
for (int k = 0; k < 3; k ) {
result = 100 - array[i] - array[j] - array[k];
if (result == 0) {
ideal = new int[]{array[i], array[j], array[k]};
return ideal;
} else {
if (result < closestResult && result > 0) {
ideal = new int[]{array[i], array[j], array[k]};
closestResult = result;
}
}
}
}
}
return ideal;
}
我現在的解決方案是手動添加更多 for 回圈和陣列元素。
示例 - 3 個數字的陣列,使用 3 個數字輸出 8 個數字的排列以最接近 100。例如。[8,13,15] 給出 [8,8,13,13,13,15,15,15] 的輸出
public static int[] mmrh8(int[] array) {
int result = 1000;
int[] ideal = new int[0];
int closestResult = 100;
for (int i = 0; i < 3; i ) {
for (int j = 0; j < 3; j ) {
for (int k = 0; k < 3; k ) {
for (int l = 0; l < 3; l ) {
for (int m = 0; m < 3; m ) {
for (int n = 0; n < 3; n ) {
for (int o = 0; o < 3; o ) {
for (int p = 0; p < 3; p ) {
result = 100 - array[i] - array[j] - array[k] - array[l] - array[m] - array[n] - array[o] - array[p];
if (result == 0) {
ideal = new int[]{array[i], array[j], array[k], array[l], array[m], array[n], array[o], array[p]};
return ideal;
} else {
if (result < closestResult && result > 0) {
ideal = new int[]{array[i], array[j], array[k], array[l], array[m], array[n], array[o], array[p]};
closestResult = result;
}
}
}
}
}
}
}
}
}
}
return ideal;
}
有沒有辦法允許 for 回圈和陣列元素的數量可變?
任何幫助表示感謝感謝!
uj5u.com熱心網友回復:
正如評論中所指出的,這個問題可能有一個更有效的解決方案,但如果你想保持你嘗試所有可能組合的蠻力方法,這里是如何做到的:
你的for-loops 所做的是有效地給出所有 8 位數字的所有可能組合,只有數字 0、1 和 2,然后將它們用作給定數字陣列中的索引。所以你需要計算這些。這可以通過列舉它們來完成:
0: 00000000
1: 00000001
2: 00000002
3: 00000010
4: 00000011
5: 00000012
6: 00000020
...
6561 (3^8): 22222222
這相當于將計數器解釋為三元系統(或任何不同的數字系統,取決于給定數字的數量)中的數字。然后可以使用此答案計算該數字的數字,將 10 換成 3 以用于三元系統。
這導致以下代碼獲得所有可能的索引組合:
// the length of the input array
int base = 3;
// must have same length as desired result length
int[] indexArray = new int[8];
// there are base to the power of length possible combinations
for (int counter = 0; counter < Math.pow(base, indexArray.length); counter ) {
// retrieve digits as in linked answer
int counterCopy = counter;
for (int i = 0; i < indexArray.length; i ) {
indexArray[i] = counterCopy % base;
counterCopy /= base;
}
// insert your code, indexArray[0] is your "i", indexArray[1] is your "j" and so on
System.out.println(Arrays.toString(indexArray));
}
uj5u.com熱心網友回復:
這是一種方法。
這個想法是生成一系列索引,這些索引將參考構成總和的候選者。例如:
- 給出最終陣列中的元素數是
8- 稱為maxElements - 填充陣列的候選串列是
{8,13,15}
然后從 生成一個索引陣列0,0,0 to 7,7,7。所以[1,3,4]會說使用一8、三13's和四15's。請注意,計數總和等于 很重要maxElements。所以1 3 4 = 8。索引陣列的創建和計數update由回傳當前索引計數的方法處理。如果該計數與maxElement值不匹配,則不會使用它來填充resultArray.
結果陣列根據當前計算出的陣列是否更接近 進行更新和保存targetSum。
Arecord用于容納和回傳最終值。class也可以使用常規。
record Results(int sum, int[] array) {
@Override
public String toString() {
return String.format("sum = %d : %s", sum,
Arrays.toString(array));
}
}
一個示例運行。
int[] candidates = { 8, 13, 15};
for (int maxElements = 1; maxElements < 10; maxElements ) {
Results result = bestSum(100, maxElements, candidates);
System.out.println(result);
}
印刷
sum = 15 : [15]
sum = 30 : [15, 15]
sum = 45 : [15, 15, 15]
sum = 60 : [15, 15, 15, 15]
sum = 75 : [15, 15, 15, 15, 15]
sum = 90 : [15, 15, 15, 15, 15, 15]
sum = 101 : [13, 13, 15, 15, 15, 15, 15]
sum = 100 : [8, 8, 13, 13, 13, 15, 15, 15]
sum = 100 : [8, 8, 8, 8, 8, 15, 15, 15, 15]
用于構建indices陣列并維護和回傳索引總和的更新方法。
public static int update(int[] indices, int prevSum,
int maxElements) {
maxElements ;
for (int i = indices.length - 1; i >= 0; i--) {
indices[i] ;
prevSum ;
if (indices[i] < maxElements) {
return prevSum;
}
prevSum -= indices[i];
indices[i] = 0;
}
return prevSum;
}
計算最佳總和的主要方法
public static Results bestSum(int targetSum, int maxElements,
int[] candidates) {
int delta = Integer.MAX_VALUE;
int[] saveResultArray = new int[maxElements];
int[] indicesArray = new int[candidates.length];
int i = maxElements;
int totalIndices = 0;
for (int v = maxElements;
v < Math.pow(maxElements 1,candidates.length); v ) {
totalIndices = update(indicesArray, totalIndices, maxElements);
// is the indices array usable, if not, ignore.
if (totalIndices != maxElements) {
continue;
}
int[] resultArray = new int[maxElements];
int nn = 0;
int tempSum = 0;
// iterate over the indices Array. For each value
// add that many of the candidates array to the result array.
for (int k = 0; k < indicesArray.length; k ) {
for (int j = 0; j < indicesArray[k]; j ) {
resultArray[nn ] = candidates[k];
tempSum = candidates[k];
}
}
// based on differences of previous computations,
// update the differences and save the result array accordingly.
if (tempSum == targetSum) {
delta = 0;
saveResultArray = resultArray;
break;
}
int diff = tempSum - targetSum;
if (Math.abs(diff) < Math.abs(delta)) {
saveResultArray = resultArray;
delta = diff;
}
}
return new Results(targetSum delta, saveResultArray);
}
這是一種蠻力演算法,其中許多值被計算后僅被忽略。隨著候選串列的增長,演算法會顯著減慢,因為這會增加回圈迭代。
uj5u.com熱心網友回復:
從您的示例中,您的解決方案似乎應該代表三個乘法因子,以應用于陣列中給定的三個值。您希望這三個因子與給定陣列值的乘積之和最接近 100。
因此,如果給定三個值 v[0]、v[1] 和 v[2],您希望求解 a、b 和 c,使得以下公式的結果最接近 100:
a * v[0] b * v[1] c * v[2]
而不是構建整個陣列,只需解決這三個值。
int maxUnder100=0;
int minOver100=99999;
for (int a=0; a<=100/v[0] 1; a ) {
for (int b=0; b<=100/v[1] 1; b ) {
for (int c=0; c<=100/v[2] 1; c ) {
int calc=a*v[0] b*v[1] c*v[2];
if (calc>=100 && calc<maxUnder100) {
maxUnder100=calc;
// store your best max solution somehow
}
if (calc<=100 && calc>minOver100) {
minOver100=calc;
// store your best min solution somehow
}
}
}
}
一旦有了這些乘法因子,表示最終的值陣列就很簡單了。
注意:我對每個 for 回圈的最大值有點看中,但肯定有改進的余地。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/403060.html
標籤:
