[英]Find all subarray with sum equal to number?
你能告訴我如何找到總和等於數字的所有子數組嗎示例
arr[] = [2, 4, 45, 6, 0, 19]
x = 51
Output: [2,4,45]
或者
arr[] = [1, 11, 100, 1, 0, 200, 3, 2, 1, 280]
x = 280
Output: [280]
我試過這樣但沒有得到正確的輸出
function getSubArray(arr, num) { var sum = 0, blank = []; var bigArr = [] for (var i = 0; i < arr.length; i++) { sum = arr[i]; if (blank.length === 0) { blank.push(arr[i]); } for (var j = 1; i < arr.length; j++) { sum += arr[j]; if (sum < num) { blank.push(arr[j]) } else if (sum > num) { sum = 0; blank = []; break; } else { blank.push(arr[j]) bigArr.push(blank); sum = 0; blank = []; } } } return bigArr } console.log(getSubArray([1, 3, 6, 11, 1, 5, 4], 4));
對於這個預期的輸出是
console.log(getSubArray([1, 3, 6, 11, 1, 5,4],4));
output: [1,3]
[4]
預期輸出 [[1,3], [4]] 是我的預期輸出
您可以迭代數組並采用下一個元素,或者如果在省略該元素之前未采用任何元素。
function getSubset(array, sum) { function iter(temp, delta, index) { if (!delta) result.push(temp); if (index >= array.length) return; iter(temp.concat(array[index]), delta - array[index], index + 1); if (!temp.length) iter(temp, delta, index + 1); } var result = []; iter([], sum, 0); return result; } console.log(getSubset([2, 4, 45, 6, 0, 19], 51)); // [2, 4, 45], [45, 6], [45, 6, 0] console.log(getSubset([1, 11, 100, 1, 0, 200, 3, 2, 1, 280], 280)); // [280] console.log(getSubset([1, 3, 6, 11, 1, 5, 4], 4)); // [1, 3], [4]
這可能不完全是需要的-可能需要進行調整,因為此處的邏輯可能存在缺陷。
我已對代碼進行注釋以進行澄清。
var arr = [1, 3, 6, 11, 1, 5,4]; // Define array var target = 31; // Define target // filter the numbers higher than target and sort rest ascending var withinRange = arr.filter(x => x <= target).sort((a, b) => a - b); if(arr.reduce((a,b) => a + b) < target) // Check if we have enough numbers to make up that number throw "The max you can get out of your selection is: " + arr.reduce((a,b) => a + b); // grab the highest number as a starting point and remove it from our array of numbers var numbers = [withinRange.pop()]; var toFind = target - getSum(); // get remainder to find for(var i = withinRange.length - 1; i > -1; i--) // iterate from the top { if(toFind == withinRange[i]){ // check if number is exactly what we need numbers.push(withinRange[i]); break; }else if(withinRange[i] <= toFind){ // if number is smaller than what we look for numbers.push(withinRange[i]); toFind -= withinRange[i]; } } function getSum(){ // sum up our found numbers if(numbers.length == 0) return 0; return numbers.reduce((a,b) => a + b); } console.log([numbers, [target]]); // print numbers as desired output console.log(target, getSum()) // print the target and our numbers
這將嘗試數組的所有可能排列(一旦達到限制,將停止進一步排列)
function test(arr, num) { // sorting will improve time as larger values will be eliminated first arr = arr.sort(function(a, b) { return b - a; }); var allLists = []; var start = Date.now(); helper(0, 0, []); console.log("Ms elapesed: " + (Date.now() - start)); return allLists || "Not found"; function helper(start, total, list) { var result = []; // Using for loop is faster because you can start from desired index without using filter, slice, splice ... for (var index = start; index < arr.length; index++) { var item = arr[index]; // If the total is too large the path can be skipped alltogether if (total + item <= num) { // Check lists if number was not included var test = helper(index + 1, total, list.concat(result)); // remove for efficiency total += item; result.push(item); //if (total === num) index = arr.length; add for efficiency } } if (total === num) allLists.push(list.concat(result)); } } console.log(test([2, 4, 45, 6, 0, 19], 51)); // [2,4,45] [2,4,45,0] [6,45] [6,45,0] console.log(test([1, 11, 100, 1, 0, 200, 3, 2, 1, 280], 280)); // [280] [280,0]
如果要提高效率,只需返回結果數組之一,只需注釋掉遞歸調用即可。 一旦達到限制,您也可以取消注釋退出循環的行(將跳過0)。
它將給出所有可用的情況。 我使用@Nina Scholz的測試用例
const sum = arr => arr.reduce((a,b) => a + b) function cal(arr, x) { const rs = [] for (let i = 0; i< arr.length; i++) { const tmp = [] for (let j=i; j<arr.length; j++ ) { tmp.push(arr[j]) if(sum(tmp) === x) rs.push([...tmp]) } } return rs } console.log(cal([1, 11, 100, 1, 0, 200, 3, 2, 1, 280], 280)) // -> [280] console.log(cal([2, 4, 45, 6, 0, 19], 51)); // -> [2, 4, 45] [45, 6] [45, 6, 0] console.log(cal([1, 3, 6, 11, 1, 5, 4], 4)); // -> [1,3] [4]
如果問題是要查找具有給定交叉和的所有子集(而不是子數組),則也稱為完美和問題。 https://www.geeksforgeeks.org/perfect-sum-problem-print-subsets-given-sum/
// A recursive function to print all subsets with the
// help of dp[][]. Vector p[] stores current subset.
function printSubsetsRec(arr, i, sum, p)
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if (i == 0 && sum != 0 && dp[0][sum])
{
p.push(arr[i]);
console.log(p);
return;
}
// If sum becomes 0
if (i == 0 && sum == 0)
{
console.log(p);
return;
}
// If given sum can be achieved after ignoring
// current element.
if (dp[i-1][sum])
{
// Create a new vector to store path
var b = p.slice(0);
printSubsetsRec(arr, i-1, sum, b);
}
// If given sum can be achieved after considering
// current element.
if (sum >= arr[i] && dp[i-1][sum-arr[i]])
{
p.push(arr[i]);
printSubsetsRec(arr, i-1, sum-arr[i], p);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets(arr, sum)
{
var n = arr.length
if (n == 0 || sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
dp = [];
for (var i=0; i<n; ++i)
{
dp[i] = []
dp[i][0] = true;
}
// Sum arr[0] can be achieved with single element
if (arr[0] <= sum)
dp[0][arr[0]] = true;
// Fill rest of the entries in dp[][]
for (var i = 1; i < n; ++i)
for (var j = 0; j < sum + 1; ++j)
dp[i][j] = (arr[i] <= j) ? dp[i-1][j] ||
dp[i-1][j-arr[i]]
: dp[i - 1][j];
if (dp[n-1][sum] == false)
{
console.log("There are no subsets with sum %d\n", sum);
return;
}
// Now recursively traverse dp[][] to find all
// paths from dp[n-1][sum]
var p = [];
printSubsetsRec(arr, n-1, sum, p);
}
printAllSubsets([1,2,3,4,5], 10);
解
'use strict';
function print(arr[], i, j) {
let k = 0;
for (k = i; k <= j; k += 1) {
console.log(arr[k]);
}
}
function findSubArrays(arr[], sum) {
let n = arr.length;
let i;
let j;
let sum_so_far;
for (i = 0; i<n; i+= 1) {
sum_so_far = 0;
for (j = i; j < n; j++) {
sum_so_far += arr[j];
if (sum_so_far === sum) {
print(arr, i, j);
}
}
}
}
我將首先根據預期數組的大小進行循環。
在該循環之后,查找數組的第一部分,該部分的第一部分應與所需數字匹配。
例如,對於具有arr = [5,4,32,8,2,1,2,2,3,4,4]的x = 4,它將首先取4。 輸出將分別從位置[1,9,10]的[[4],[4],[4],....]開始
然后對結果為2個元素[... [2,2],[2,2],[2,2],[1,3] ...]的數組求和(位置4 + 6,位置4+ 7 position6 + 7和position 5 + 8)此時您可能想要使用另一個函數進行求和和檢查。
現在將對3個元素的總和(如果有的話)執行相同的操作,依此類推,將max循環設置為原始數組的數量(結果數量可能是數組中所有元素的總和)。
結果示例將是[[4],[4],[4],[2,2],[2,2],[2,2],[1,3]]
function combinations(array) {
return new Array(1 << array.length).fill().map(
(e1,i) => array.filter((e2, j) => i & 1 << j));
}
function add(acc,a) {
return acc + a
}
combinations([2, 4, 45, 6, 0, 19]).filter( subarray => subarray.reduce(add, 0) == 51 )
輸出
[[2,4,45],[45,6],[2,4,45,0],[45,6,0]]
combinations([1, 11, 100, 1, 0, 200, 3, 2, 1, 280]).filter( subarray => subarray.reduce(add, 0) == 280 )
輸出
[[280],[0,280]]
如果這些元素嚴格意義上是積極的,則可以一次收集此類子序列,並以蠕蟲/毛毛蟲般的方式前進:伸展其前端以增加總和(當它在目標以下時)並向后收縮為了降低總和:
function worm(arr,target){ var ret=[]; var head=0; var tail=0; var sum=0; while(head<arr.length){ while(sum<=target && head<arr.length){ sum+=arr[head++]; if(sum===target) ret.push(arr.slice(tail,head)); } while(sum>=target && tail<head){ sum-=arr[tail++]; if(sum===target) ret.push(arr.slice(tail,head)); } } return JSON.stringify(arr)+": "+JSON.stringify(ret); } console.log(worm([2, 4, 45, 6, 19], 51)); console.log(worm([1, 11, 100, 1, 200, 3, 2, 1, 280], 280)); console.log(worm([1, 3, 6, 11, 1, 5, 4], 4)); console.log("But it only occasionally finds 0+... / ...+0 sums:"); console.log(worm([2, 4, 45, 6, 0, 19], 51)); console.log(worm([2, 4, 0, 45, 0, 6, 0, 19], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19], 51));
解決與邊界零相關的問題的一種方法是丟棄此類序列。 此代碼段將tail
和head(-1)
保留在非零元素上:
function worm(arr,target){ var ret=[]; var head=0; while(head<arr.length && arr[head]===0)head++; var tail=head; var sum=0; while(head<arr.length){ while(sum<=target && head<arr.length){ while(head<arr.length && arr[head]===0)head++; sum+=arr[head++]; if(sum===target) ret.push(arr.slice(tail,head)); } while(sum>=target && tail<head){ sum-=arr[tail++]; while(tail<head && arr[tail]===0)tail++; if(sum===target) ret.push(arr.slice(tail,head)); } } return JSON.stringify(arr)+": "+JSON.stringify(ret); } console.log(worm([2, 4, 45, 6, 19], 51)); console.log(worm([1, 11, 100, 1, 200, 3, 2, 1, 280], 280)); console.log(worm([1, 3, 6, 11, 1, 5, 4], 4)); console.log(worm([2, 4, 45, 6, 0, 19], 51)); console.log(worm([2, 4, 0, 45, 0, 6, 0, 19], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19, 26], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19, 26, 0], 51)); console.log(worm([1,8,2], 10)); console.log(worm([0,1,0,8,2,0], 10)); console.log(worm([0,8,2,8,0], 10)); console.log(worm([0,8,0,2,0,8,0], 10));
如果有人確實需要這些0+...
/ ...+0
序列,那么代碼將失去所有剩余的美感,因為它們必須在后處理步驟中生成:
function worm(arr,target){ var pairs=[]; var head=0; while(head<arr.length && arr[head]===0)head++; var tail=head; var sum=0; while(head<arr.length){ while(sum<=target && head<arr.length){ while(head<arr.length && arr[head]===0)head++; sum+=arr[head++]; if(sum===target) pairs.push([tail,head]); } while(sum>=target && tail<head){ sum-=arr[tail++]; while(tail<head && arr[tail]===0)tail++; if(sum===target) pairs.push([tail,head]); } } var ret=[]; for([tail,head] of pairs){ (function pre(tail,head){ ret.push(arr.slice(tail,head)); if(tail>0 && arr[tail-1]===0) pre(tail-1,head); (function post(tail,head){ if(head<arr.length && arr[head]===0){ ret.push(arr.slice(tail,head+1)); post(tail,head+1); } })(tail,head); })(tail,head); } return JSON.stringify(arr)+": "+JSON.stringify(ret); } console.log(worm([2, 4, 45, 6, 19], 51)); console.log(worm([1, 11, 100, 1, 200, 3, 2, 1, 280], 280)); console.log(worm([1, 3, 6, 11, 1, 5, 4], 4)); console.log(worm([2, 4, 45, 6, 0, 19], 51)); console.log(worm([2, 4, 0, 45, 0, 6, 0, 19], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19, 26], 51)); console.log(worm([0, 2, 4, 0, 45, 0, 6, 0, 19, 26, 0], 51)); console.log(worm([1,8,2], 10)); console.log(worm([0,1,0,8,2,0], 10)); console.log(worm([0,8,2,8,0], 10)); console.log(worm([0,8,0,2,0,8,0], 10));
我認為它適用於(非負元素),但是第一個肯定更簡單。
帶地圖和過濾器
const arr = [2, 4, 45, 6, 0, 19] let t = 0 const result = arr.map((v,i)=>{ return [v, t += v] }).filter((v,i)=>v[1]<=51) console.log(result)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.