簡體   English   中英

找到總和等於數字的所有子數組?

[英]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)); 

解決與邊界零相關的問題的一種方法是丟棄此類序列。 此代碼段將tailhead(-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM