【问题标题】:SubSet sum with N array Solution, Dynamic Solution recquired子集和 N 数组解,需要动态解
【发布时间】:2017-11-13 04:08:30
【问题描述】:

虽然您可以拥有任意数量的 arrays,但假设您有两个 arrays {1,2,3,4,5,6} 和 {1,2,3,4,5,6 } 您必须在 array 两个元素的参与下找出它们的总和是否为 4。即

1 from array1, 3 from array2
2 from array1, 2 from array2
3 from array1, 1 from array2

简而言之:想要实现子集求和算法,其中有两个数组,并从两个数组中选择数组元素来组成目标和

这是我用于array子集总和算法

bool subset_sum(int a[],int n, int sum)
{
 bool dp[n+1][sum+1];


   int i,j;

   for(i=0;i<=n;i++)   
      dp[i][0]=true;

   for(j=1;j<=sum;j++)
        dp[0][j]=false;

   for(i=1;i<=n;i++)

    {

        for(j=1;j<=sum;j++)

       {

           if(dp[i-1][j]==true)

              dp[i][j]=true;

           else
           {

               if(a[i-1]>j)

                   dp[i][j]=false;

                else

                    dp[i][j]=dp[i-1][j-a[i-1]];

            }

        }

    }
  return dp[n][sum];
}

【问题讨论】:

  • 所有阵列的参与是必须的吗?
  • 最初的“掷骰子”公式更加清晰。
  • 是的,两个数组都必须参与
  • -MBo 我认为这会令人困惑
  • @Andrew Watson 现在看起来完全不同的问题。并且不清楚。你最好表现出真正的问题。

标签: algorithm dynamic-programming subset-sum


【解决方案1】:

我们可以使用 3 维 dp 来实现这一点。但为了简单和可读性,我使用两种方法编写它。

注意:当我们从每个array 中选择至少一个元素 时,我的解决方案有效。如果存在我们必须从每个array 中选择相等数量的元素的条件,则它不起作用。

// This is a helper method

//  prevPosAr[] is the denotes what values could be made with participation from ALL
// arrays BEFORE the current array

// This method returns an array which denotes what values could be made with the
// with participation from ALL arrays UP TO current array


boolean[] getPossibleAr( boolean prevPossibleAr[], int ar[] )
{
    boolean dp[][] = new boolean[ ar.length + 1 ][ prevPossibleAr.length  ];
    // dp[i][j] denotes   if we can make value j using AT LEAST
    // ONE element from current ar[0...i-1]

    for (int i = 1; i <= ar.length; i++)
    {
        for (int j = 0; j < dp[i].length; j++)
        {
            if ( dp[i-1][j] == true )
            {
                // we can make value j using AT LEAST one element from ar[0...i-2]
                // it implies that we can also make value j using AT LEAST
                // one element from ar[0...i-1]
                dp[i][j] = true;
                continue;
            }

            int prev = i-ar[i-1];
            // now we look behind


            if ( prev < 0 )
            {
                // it implies that ar[i-1] > i
                continue;
            }

            if ( prevPossibleAr[prev] || dp[i-1][prev] )
            {
                // It is the main catch
                // Be careful


                // if ( prevPossibleAr[prev] == true )
                // it means that we could make the value prev
                // using the previous arrays (without using any element
                // of the current array)
                // so now we can add ar[i-1] with prev and eventually make i



                // if ( dp[i-1][prev] == true )
                // it means that we could make prev using one or more
                // elements from the current array....
                // now we can add ar[i-1] with this and eventually make i

                dp[i][j] = true;
            }
        }
    }

    // What is dp[ar.length] ?
    // It is an array of booleans
    // It denotes whether we can make value j using ALL the arrays 
    // (using means taking AT LEAST ONE ELEMENT)
    // before the current array and using at least ONE element 
    // from the current array ar[0...ar.lengh-1] (That is the full current array)

    return dp[ar.length];
}



// This is the method which will give us the output
boolean subsetSum(int  ar[][], int sum )
{
    boolean prevPossible[] = new boolean[sum+1];
    prevPossible[0] = true;


    for ( int i = 0; i < ar.length; i++ )
    {
        boolean newPossible[] = getPossibleAr(prevPossible, ar[i]); 
        // calling that helper function
        // newPossible denotes what values can be made with
        // participation from ALL arrays UP TO i th array
        // (0 based index here)



        prevPossible = newPossible;
    }

    return prevPossible[sum];
}

【讨论】:

  • 非常感谢您的辛勤工作并投了赞成票。您能否评论一下您在 for 循环中所做的工作?
  • @AndrewWatson,我的解决方案中有几个 for 循环。您能否指出您希望获得评论的 for 循环?
  • 感谢关注。getPossibleAr函数内部。
  • @AndrewWatson,我在该区域添加了更多 cmets。如果您有任何问题需要了解,请告诉我。
  • @AndrewWatson,我很高兴。我很高兴回答你的问题。
【解决方案2】:

步骤,

find (Array1, Array2, N)
  sort Array1
  sort Array2

  for (i -> 0 && i < Array1.length) and (j -> Array2.length-1 && j >= 0)
    if(Array1[i] + Array2[j] == N)
      return yes;
    if(Array1[i] + Array2[j] > N)
      j--;
    else
      i++;
  return NO;

【讨论】:

  • 它不是动态解决方案,仅限于两个数组。请提供动态解决方案
  • 动态解是什么意思?你预期的复杂性是什么?如果您想使用两个以上的数组,请在问题中明确提及。
  • 实际上我想实现子集求和算法,其中有两个数组,元素是从两个不同的数组中选择的。我提供了用于实现子集和算法的代码,其中只有数组。
猜你喜欢
  • 2011-08-11
  • 1970-01-01
  • 2015-01-19
  • 2016-05-15
  • 1970-01-01
  • 2014-09-09
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
相关资源
最近更新 更多