可以为范围

时间:2017-07-10 18:49:54

标签: algorithm

问题陈述:

您将获得两个数字,即A和S.编写程序以查找可以添加大于或等于S的数字的方式的数量以获得总和A.以模10的形式打印结果^ 9 + 9

e.g。如果A为3且S为1,则有三种方法可以使用大于等于S = 1的数字来实现A = 3。溶液是< 1,1,1>,< 1,2>。和< 3>。 对于A = 9和S = 3,溶液将是< 3,3,3>,< 3,6>,< 4,5>。和< 9>。共有4种方法可以使用大于等于3的数字来获得9。

我使用了以下方法。

  1. 检查是否(S> A / 2)然后只有一种解决方案可能。例如,如果A = 9和 S = 5然后只有一种解决方案可能是< 9>。
  2. 如果条件1不为真,则创建一个列表并存储所有i 列表中的S< = i< = A / 2.
  3. 对于列表中的每个号码。

    3.1。而A> = i

    3.1.1。通过i减少A.

    3.1.2。如果A> = i,则增加计数(计数存储总排列,并且是    最初设为1)。

    3.1.3。否则就会退出。

  4. 这种方法具有二次时间复杂度。有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:0)

我能够使用动态编程解决这个问题。问题类似于硬币变化问题,其中总和是我们的总金额,d,d + 1,d + 2,..,sum是我们可用于实现总和的硬币。下面是我写的java代码。

private static int countPartitionsDP(int d, int sum){
    if(d>sum/2)
        return 1;
    if(d>sum)
        return 0;
    int coins=sum-d+1;
    int[][] dp=new int[coins][sum+1];
    for(int i=0;i<coins;i++){   //for sum=5 and d=2 number that we use to achieve sum is 2,3,4,5 i.e (i+d).
        for(int j=0;j<=sum;j++){
            if(j==0)    //sum=0 can be achieved in 1 way. dp[i][0]=1
                dp[i][j]=1;
            else if(i==0){
                if(j<(i+d)){    //if current sum j is less than current value of d i.e.(i+d).
                    dp[i][j]=0;
                }else{
                    dp[i][j]=dp[i][j-i-d];  //if sum is greater than current value of d then dp[i][j]=dp[i][j-d]
                }
            }else if(j<(i+d)){
                dp[i][j]=dp[i-1][j];
            }else{
                dp[i][j]=dp[i-1][j]+dp[i][j-i-d];
            }
        }
    }
    return dp[coins-1][sum];
}