如何从数组中找到3个数字的组合,当添加时,它等于另一个给定的数字

Posted

技术标签:

【中文标题】如何从数组中找到3个数字的组合,当添加时,它等于另一个给定的数字【英文标题】:How to find a combination of 3 numbers from an array that, when added, equals another given number 【发布时间】:2019-08-13 19:36:53 【问题描述】:

我有一个包含多个数字的数组。我希望函数从数组中返回另一个最多包含 3 个数字的数组,当它们相加时,等于另一个数字。

也可以是 1 或 2 个数字,但第一个数字必须是最大的。

例如:

    var array = [1,2,3,4,5,6,7,8,9,10];
    var number: 25;

期望的输出:[10,10,5]

或者

    var array = [1,2,3,4,5,6,7,8,9,10];
    var number: 11;

期望的输出:[10,1]

或者

    var array = [1,2,3,4,5,6,7,8,9,10];
    var number: 5;

期望的输出:[5]

您可能会看到,我正在构建一个小型 dart 应用程序来计算您的分数。这是我需要展示的最后一部分,无论我投了多少飞镖,哪种飞镖组合都能让你准确地达到 0。

我可以遍历我的数字并将它们放入一个数组中,但只要组合需要在另一个之前有一个较小的数字,它就无法计算。代码如下:


// the numbers to add
var finishingNumbers = [60, 57, 54, 51, 50, 48, 45, 42, 40, 39, 38, 36, 34, 33, 32, 30, 28, 27, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];

// The number
var output = 167;

// The variable for the end result
var dartsToFinishArr = [];

// Call my function
checkArray();

function checkArray() 
    for (var j = 0; j < finishingNumbers.length; j++) 
        var dartsToFinishArrTotal = 0;
        if (dartsToFinishArr.length > 0) 
            for (n = 0; n < dartsToFinishArr.length; n++) 
                dartsToFinishArrTotal += dartsToFinishArr[n];
            
        

        if (output <= 180) 
            if (finishingNumbers[j] + dartsToFinishArrTotal == +($(".matchContainer .matchPlayerContainer .player.playerTurn .playerScore .value").text()) && dartsToFinishArr.length < 3) 
                dartsToFinishArr.push(finishingNumbers[j]);
                return;
             else if (finishingNumbers[j] + dartsToFinishArrTotal < output && dartsToFinishArr.length < 3) 
                dartsToFinishArr.push(finishingNumbers[j]);
                checkArray();

                return;
             else if (dartsToFinishArrTotal != output) 
            return;
            
        
    


这应该给我:

    var dartsToFinishArr = [60, 57, 50]

但是没有

【问题讨论】:

你尝试过什么(用文字而不是代码)?您是将数组排序为升序还是降序?如果数组已排序,您应该能够通过按顺序(或以相反顺序)循环来做到这一点,以便您首先尝试最大的数字。 【参考方案1】:

下面的逻辑遍历所有组合,直到找到三个符合您总数的数字。如果它们满足总数,它还会缩短到少于三个数字。

// the numbers to add
var finishingNumbers = [60, 57, 54, 51, 50, 48, 45, 42, 40, 39, 38, 36, 34, 33, 32, 30, 28, 27, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];

// The number
var output = 167;

console.log( findValues( finishingNumbers, output ) );

function findValues ( numbers, desiredTotal ) 
  numbers = numbers.slice(0).sort((a, b)=>b-a) //sort descending
  
  for ( let i = 0; i < numbers.length; i++ ) 
    if ( numbers[ i ] === desiredTotal ) return [ numbers[ i ] ];
    
    // add in the numbers after the previous number at `i`
    for ( let j = i + i; j < numbers.length; j++ ) 
      if ( numbers[ i ] + numbers[ j ] === desiredTotal ) return [ numbers[ i ], numbers[ j ] ];
      
      // add in the numbers after the previous number at `j`
      for ( let k = j + 1; k < numbers.length; k++ ) 
        if ( numbers[ i ] + numbers[ j ] + numbers[ k ] === desiredTotal ) return [ numbers[ i ], numbers[ j ], numbers[ k ] ];
      
    
  

【讨论】:

这段代码看起来很简洁!我无法在我的程序中测试它 2 天,但我相信它会很好地完成这项工作。我会尽快告诉你它是否对我有用。非常感谢!【参考方案2】:

。 我试图解决它,并且我的这段代码运行良好。

我没有尝试过javascript编程,但我有C++的解决方案代码,所以你可以检查算法:

int numbersList[10] = 1,2,3,4,5,6,7,8,9,10;
    int targetNumber;

    cout<<"Enter target number: ";
    cin>>targetNumber;

    int a=numbersList[9], b=numbersList[9], c=numbersList[9];

    if (a+b+c==targetNumber)
    
        cout<<"Answer: a="<<a<<" b="<<b<<" c="<<c<<endl;
     else 
        int aPos=9, bPos=9, cPos=9;
        for(int i=0 ; i<719 ; i++)
        
            a = numbersList[aPos];
            b = numbersList[bPos];
            c = numbersList[cPos];
            if (a+b+c==targetNumber)
            
                cout<<"Possible! a="<<a<<" b="<<b<<" c="<<c<<endl;
                //break;
             else if (a+b+c>targetNumber)
            
                if (cPos==0)
                
                    if (bPos==0)
                    
                        if (aPos==0)
                        
                            cout<<"Not possible!"<<endl;
                            break;
                         else 
                            aPos -=1;
                        
                     else 
                        bPos -=1;
                    
                 else 
                    cPos -=1;
                
            
        
    

如果你想查看程序,你可以在这里尝试-> Click me

然后粘贴这段代码:

/******************************************************************************

                              Online C++ Compiler.
               Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/

#include <iostream>

using namespace std;

int main()

    int numbersList[10] = 1,2,3,4,5,6,7,8,9,10;
    int targetNumber;

    cout<<"Enter target number: ";
    cin>>targetNumber;

    int a=numbersList[9], b=numbersList[9], c=numbersList[9];

    if (a+b+c==targetNumber)
    
        cout<<"Answer: a="<<a<<" b="<<b<<" c="<<c<<endl;
     else 
        int aPos=9, bPos=9, cPos=9;
        for(int i=0 ; i<719 ; i++)
        
            a = numbersList[aPos];
            b = numbersList[bPos];
            c = numbersList[cPos];
            if (a+b+c==targetNumber)
            
                cout<<"Possible! a="<<a<<" b="<<b<<" c="<<c<<endl;
                //break;
             else if (a+b+c>targetNumber)
            
                if (cPos==0)
                
                    if (bPos==0)
                    
                        if (aPos==0)
                        
                            cout<<"Not possible!"<<endl;
                            break;
                         else 
                            aPos -=1;
                        
                     else 
                        bPos -=1;
                    
                 else 
                    cPos -=1;
                
            
        
    
    return 0;

希望你能得到答案:)

【讨论】:

如果您发现代码有任何问题,请告诉我。【参考方案3】:

这是我在 javascript 中解决您的问题的尝试:

// the numbers to add
var finishingNumbers = [60, 57, 54, 51, 50, 48, 45, 42, 40, 39, 38, 36, 34, 33, 32, 30, 28, 27, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];

// The number
var output = 167;

// The variable for the end result
var dartsToFinishArr = [];

for (let i = 0; i < finishingNumbers.length; i++) 
  const element1 = finishingNumbers[i];
  if (element1 === output) 
    dartsToFinishArr = [element1];
    return;
  

  for (let j = 0; j < finishingNumbers.length; j++) 
    const element2 = finishingNumbers[j];
    if (element1 + element2 == output) 
      dartsToFinishArr = [element1, element2];
      return;
    

    for (let k = 0; k < finishingNumbers.length; k++) 
      const element3 = finishingNumbers[k];
      if (element1 + element2 + element3 === output) 
        dartsToFinishArr = [element1, element2, element3];
        return;
      
    
  

这似乎是"how to debug a small program" 的一个相当典型的案例,我强烈建议您阅读整篇博文,因为它会显着提高您的编程技能。

现在我们有了一个可行的解决方案,让我们玩得开心吧!此解决方案满足您的要求,但您注意到我有 3 个嵌套的 for 循环。这不是很糟糕,但是如果您的要求改变为在您的解决方案中包含 任何 数量的数字,我的代码将很快在复制和粘贴的混乱中爆炸。我们能否构建一个解决方案,将解决方案中的数字数量纳入其中并始终能够计算出来?你打赌!这是recursion 的完美场景。

这里有一个更复杂但更通用的解决方案:

// the numbers to add
var finishingNumbers = [60, 57, 54, 51, 50, 48, 45, 42, 40, 39, 38, 36, 34, 33, 32, 30, 28, 27, 26, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];

// The number
var output = 167;

// The variable for the end result
var dartsToFinishArr = [];

// The maximum amount of numbers allowed in the solution;
const maxNumbers = 3;

function sum(total, element) 
  return total + element;


function recursiveSolution(possibleSolution) 
  for (let element of finishingNumbers) 

    // Special case when we haven't added anything to the solution yet
    var total = element;
    if (possibleSolution.length > 0) 
      total = possibleSolution.reduce(sum) + element;
    

    if (total === output) 
      dartsToFinishArr = possibleSolution;
      dartsToFinishArr.push(element);

      //Solution found, return recursively.
      return true;
    

    if (total < output && possibleSolution.length < maxNumbers - 1) 
      //There's room for more numbers, continue recursively
      const newPossibleSolution = possibleSolution.slice(0);
      newPossibleSolution.push(element);
      if (recursiveSolution(newPossibleSolution)) 
        //The recursion worked, return recursively.
        return true;
      
    
  

  //We tried everything with the current possible solution. Let's backtrack one number and try the next one.
  return false;


// Start the recursion with an empty solution
recursiveSolution([]);

console.debug(dartsToFinishArr);

现在你可以修改maxNumbers,你可以得到任何你想要的解决方案!

【讨论】:

我要等到 2 天才能测试,但是您链接的文章非常有趣且有用。如果您的答案很快奏效,我会通知您。非常感谢互联网陌生人! 没问题。我添加了另一个使用递归的解决方案供您学习。祝你好运!

以上是关于如何从数组中找到3个数字的组合,当添加时,它等于另一个给定的数字的主要内容,如果未能解决你的问题,请参考以下文章

PHP数组组合

如何找到从多个数组中提取的数字的最小总和?

如何将sender()名称转换为int [duplicate]

求一个数组的数字有几种组合方式,6个数相加等于100.用PHP写的程式

如何优化数字组合的 vba 代码

计算组合的有效算法,数组的重复加起来等于给定的总和