Это можно рассматривать как проблему оптимизации, которая хорошо подходит для динамического программирования .
Это означает, что вы разбили бы его на рекурсию, которая пытается найти минимальную длину все меньших массивов с суммой, скорректированной с учетом того, что было удалено. Если ваш массив равен [10, 0, -1, 20, 25, 30]
с суммой 59
, вы можете думать о самом коротком как о min
из:
[10, ... shortest([ 0, -1, 20, 25, 30], 49)
[0, ... shortest([10, 20, 25, 30], 49), 59)
[-1, ... shortest([10, 0, 20, 25, 30], 60)
... continue recursively
с каждой рекурсией, если массив становится короче до тех пор, пока у вас не останется один элемент, тогда вопрос в том, равен ли этот элемент числу, оставшемуся после всех вычитаний.
Проще показать в коде:
function findMinSum(arr, n){
if(!arr) return
let min
for (let i=0; i<arr.length; i++) {
/* if a number equals the sum, it's obviously
* the shortest set, just return it
*/
if (arr[i] == n) return [arr[i]]
/* recursively call on subset with
* sum adjusted for removed element
*/
let next = findMinSum(arr.slice(i+1), n-arr[i])
/* we only care about next if it's shorter then
* the shortest thing we've seen so far
*/
if (next){
if(min === undefined || next.length < min.length){
min = [arr[i], ...next]
}
}
}
return min && min /* if we found a match return it, otherwise return undefined */
}
console.log(findMinSum([10, 0, -1, 20, 25, 30], 59).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], 29).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], -5)) // undefined when no sum
Это все еще довольно затратная вычислительная система, но она должна быть намного быстрее, чем поиск всех подмножеств и сумм.