[英]Creating all possible combinations sorted by sum
給定一組任意數字S = {1..n}
和大小k
,我需要打印按總和排序的大小k
所有可能組合。
假設S = {1, 2, 3, 4, 5}
和k = 3
,示例輸出將是:
1 2 3 = 6
1 2 4 = 7
1 2 5 = 8
1 3 4 = 8
1 3 5 = 9
2 3 4 = 9
2 3 5 = 10
1 4 5 = 10
2 4 5 = 11
3 4 5 = 12
我想到的第一個想法是對S
進行排序(如果尚未排序),然后執行 BFS 搜索,將組合隊列按總和排序。 這是因為我只想在請求時生成下一個組合(類似迭代器)。 但這似乎有點矯枉過正,我認為應該有一個更簡單的解決方案。 如何解決這個問題?
編輯:
這是我最初的想法:
1. Sort S
2. Pick the first k numbers and add them to the queue as a single node (because this is the combination with the smallest sum)
3. While the queue is not empty - pop the first node, output it, and generate successors.
Generating successors:
1. Start with the first number in the node. Make a copy of a node. Find the smallest unselected value that is > than the number, and assign this value.
2. Verify that this node hasn't been seen and calculate the sum.
3. Add the node to the queue.
4. Repeat 1-3 for all of the remaining numbers in the node.
例子:
Queue q = { {1, 2, 3} = 6 }
Pop front, output
1 2 3 = 6
Generate {4, 2, 3} = 9, {1, 4, 3} = 8, {1, 2, 4} = 7
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4} }
Queue q = { {1, 2, 4} = 7, {1, 4, 3} = 8, {4, 2, 3} = 9 }
Pop front, output
1 2 3 = 6
1 2 4 = 7
Generate {3, 2, 4} = 9 (seen - discard), {1, 3, 4} = 8 (seen - discard), {1, 2, 5} = 8 }
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4}, {1, 2, 5} }
Queue q = { {1, 2, 5} = 8, {1, 4, 3} = 8, {4, 2, 3} = 9 }
Pop front, output
1 2 3 = 6
1 2 4 = 7
1 2 5 = 8
Generate {3, 2, 5} = 10, {1, 3, 5} = 9
Seen { {1, 2, 3}, {4, 2, 3}, {1, 4, 3}, {1, 2, 4}, {1, 2, 5}, {3, 2, 5}, {1, 3, 5} }
Queue q = { {1, 4, 3} = 8, {1, 5, 3} = 9, {1, 3, 5} = 9, {3, 2, 5} = 10, {1, 4, 5} = 10, {4, 2, 5} = 11 }
...
...
如下所示的 javascript 示例;
<!DOCTYPE html>
<html>
<head>
<meta charset = utf-8>
<title>s{1..n} by k</title>
</head>
<body>
<header>s{1..n} by k</header>
<form action="#" onsubmit="return false;">
s:<input type="text" id="sArrayObj" name="sArrayObj" value="4 5 1 8 9 3 6 7"/><br/>
n:<input type="text" id="kVarObj" name="kVarObj" value="3"/><br/>
<button id="scan" name="scan" onclick="scanX()"> CALCULATE </button><br/>
<textarea id="scanned" name="scanned" cols=40 rows=20>
</textarea>
</form>
<script>
const headFactorial = n => {
if ( n > 1 ) return n * headFactorial( n - 1 );
else return 1;
}
const tailFactorial = n => {
if ( n === 1 ) return 1;
else return n * tailFactorial( n - 1 );
}
const combinations = ( collection, combinationLength ) => {
let head, tail, result = [];
if ( combinationLength > collection.length || combinationLength < 1 ) { return []; }
if ( combinationLength === collection.length ) { return [ collection ]; }
if ( combinationLength === 1 ) { return collection.map( element => [ element ] ); }
for ( let i = 0; i < collection.length - combinationLength + 1; i++ ) {
head = collection.slice( i, i + 1 );
tail = combinations( collection.slice( i + 1 ), combinationLength - 1 );
for ( let j = 0; j < tail.length; j++ ) { result.push( head.concat( tail[ j ] ) ); }
}
return result;
}
const sumArr = (anArr) => {
var s=0;
for (j=0; j < anArr.length; j++) s += 1*anArr[j];
return s;
}
function scanX(){
sArray = document.getElementById("sArrayObj").value.split(" ");
kVar = document.getElementById("kVarObj").value;
sArray.sort();
resultObj= document.getElementById("scanned");
resultObj.value = "";
//for (i=0;kVar > i;i++){
// resultObj.value+=sArray[i]+' ';
//}
resultArr = combinations(sArray, kVar);
for (i=0;i<resultArr.length;i++){
resultObj.value += resultArr[i]+"="+sumArr(resultArr[i])+"\n";
}
return false;
}
</script>
</body>
</html>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.