【问题标题】:Find if a given number is a sum of a given set (with repetitons allowed) using recursion (java)使用递归(java)查找给定数字是否是给定集合(允许重复)的总和
【发布时间】:2012-11-18 11:22:46
【问题描述】:

我试图找出给定数字是否是给定集合的总和, 例如:数字12是集合s{3,2}的总和, 因为:

3+3+3+3=12
or
2+2+2+2+2+2=12

14 不是s{8,10} 的总和,因为您不能用sums of s 创建数字14。 我正在尝试仅使用递归而不使用循环在 java 中编写代码。 这是代码:

   public static boolean isSumOf(int[]s,int n)
   {
     return isSumOf(s,n,0,0,0);
   }


   private static boolean isSumOf(int[]s,int n,int i,int sum,int m)
   {
       boolean with=false;
       boolean without=false;

       if(i==s.length)
        return false;

       if(sum==n)   
        return true;

       if(m<=n)
        {
            with=isSumOf(s,n,i,sum+s[i]*m,m++);
            without=isSumOf(s,n,i,sum,m++);            
        }
       else
        {
            i=i++;
            m=0;
            isSumOf(s,n,i,sum,m);
        }

       return (with||without); 

   }

代码编译正常,但是当我对其运行测试时出现 stackOverFlowError。 这是测试的代码:

  public static void main(String[]args)
  {  
      int[]a={18,10,6};
      int x=18+10+6;
      System.out.println(Ex14.isSumOf(a,x));
  }

请帮忙!!!

【问题讨论】:

  • 只是好奇.. 为什么对这个问题投反对票?我认为它明确指定了 OP 想要什么。还有他试过的代码吗?
  • 堆栈溢出表明您的代码没有终止。您是否通过一个简单的示例逐步使用调试器来查看为什么您的 return 语句没有执行?
  • 我建议您重命名方法中的变量。很难确定 nim 指的是什么。它也可以帮助您发现错误。

标签: java recursion sum subset stack-overflow


【解决方案1】:

这看起来很糟糕:

with=isSumOf(s,n,i,sum+s[i]*m,m++);
without=isSumOf(s,n,i,sum,m++);

使用

with=isSumOf(s,n,i,sum+s[i]*m,++m);
without=isSumOf(s,n,i,sum,++m);

如果你想让m 在被调用的方法中高一级。

除此之外,由于变量命名不佳,我不知道代码做了什么。

还有这一行:

i=i++;

没有效果,如果要增加i,请用以下之一替换:

i++;
i += 1;
i = i + 1;
i = ++i;

如果你不使用调用的结果

isSumOf(s,n,i,sum,m); 

调用它没有意义。

【讨论】:

    【解决方案2】:

    这似乎可行 - 我没有看到任何迹象表明您不想要现成的答案(如果这是家庭作业,我相信您会说明)所以这里是:

    public class IsSumOf {
      // set - The numbers allowed.
      // total - The number I want to achieve.
      // i - Where we are in the set.
      // sum - List of numbers used so far.
      // n - The number we just subtracted (or 0 if none).
      // Note that sum and n are only used for the printing of the route.
      private static boolean isSumOf(int[] set, int total, int i, LinkedList<Integer> sum, int n) {
        // Found the set if we are now at 0.
        boolean is = (total == 0);
        // Look no further if no more to try.
        if ( total > 0 ) {
          // Look no further if we've exhausted the array.
          if ( i < set.length ) {
            // Try or consume this number in the set (or not) and try again.
            is = isSumOf(set, total - set[i], i, sum, set[i] ) 
                    || isSumOf(set, total - set[i], i+1, sum, set[i] ) 
                    || isSumOf(set, total, i+1, sum, 0 ) ;
          }
        }
        // Keep track of the route.
        if ( is && sum != null && n != 0) {
          // Add backwards so we get the order right when printed.
          sum.addFirst(n);
        }
        return is;
      }
    
      // Jump-off point.
      public static boolean isSumOf(int[] set, int total, LinkedList<Integer> sum) {
        // Empty the list.
        sum.clear();
        // Start at 0 in the array.
        return isSumOf(set, total, 0, sum, 0);
      }
    
      public static void main(String[] args) {
        LinkedList<Integer> sum = new LinkedList<Integer>();
        int[] a = {18, 10, 6};
        int x = 18 + 10 + 6;
        System.out.println(Arrays.toString(a)+" ("+x+") = "+(isSumOf(a, x, sum)?Arrays.toString(sum.toArray()):"-"));
        x += 1;
        System.out.println(Arrays.toString(a)+" ("+x+") = "+(isSumOf(a, x, sum)?Arrays.toString(sum.toArray()):"-"));
        int[] b = {3,2};
        x = 12;
        System.out.println(Arrays.toString(b)+" ("+x+") = "+(isSumOf(b, x, sum)?Arrays.toString(sum.toArray()):"-"));
        x += 1;
        System.out.println(Arrays.toString(b)+" ("+x+") = "+(isSumOf(b, x, sum)?Arrays.toString(sum.toArray()):"-"));
        int[] c = {2,3};
        x = 12;
        System.out.println(Arrays.toString(c)+" ("+x+") = "+(isSumOf(c, x, sum)?Arrays.toString(sum.toArray()):"-"));
        x += 1;
        System.out.println(Arrays.toString(c)+" ("+x+") = "+(isSumOf(c, x, sum)?Arrays.toString(sum.toArray()):"-"));
      }
    }
    

    已编辑以打印所走的路线。

    打印:

    [18, 10, 6] (34) = [18, 10, 6]
    [18, 10, 6] (35) = -
    [3, 2] (12) = [3, 3, 3, 3]
    [3, 2] (13) = [3, 3, 3, 2, 2]
    [2, 3] (12) = [2, 2, 2, 2, 2, 2]
    [2, 3] (13) = [2, 2, 2, 2, 2, 3]
    

    【讨论】:

    • 在这种情况下@Martin 请务必学习我的技术,尽量不要复制我的代码。你自己做会明白很多。将来,如果您发布涉及家庭作业的问题,您最好明确说明并要求不要发布完整的解决方案。我希望我没有损害你为这件作品获得好成绩的机会。请记住,您的老师也可以访问 SO。
    【解决方案3】:

    我会使用稍微不同的策略

    public static void main(String[] args)
    {
        int[] s = { 4, 5 };
        System.out.println(isSumOf(s, 13)); // true
        System.out.println();
    
        int[] s1 = { 4, 9, 3 };
        System.out.println(isSumOf(s1, 15)); // true
        System.out.println();
    
        int[] s2 = { 4, 9, 3 };
        System.out.println(isSumOf(s2, 5)); // false
        System.out.println();
    
        int[] s3 = { 3, 2 };
        System.out.println(isSumOf(s3, 12)); // true
        System.out.println();
    
        int[] s4 = { 8, 10 };
        System.out.println(isSumOf(s4, 14)); // false
        System.out.println();
    }
    
    public static boolean isSumOf(int[] s, int n)
    {
        return isSumOf(s, n, 0, 0, "");
    }
    
    private static boolean isSumOf(int[] s, int n, int i, int sum, String builder)
    {
        if (sum == n) // if we found a subset
        {
            System.out.println(builder);
            return true;
        }
    
        if (i == s.length || sum > n) // 1. boundaries checks 2. if subset is greater then n
            return false;
    
        boolean with = isSumOf(s, n, i, sum + s[i], builder + s[i] + " "); // try to sum "s[i]", note that we can sum the
                                                                            // same "s[i]" multiple times
    
        boolean without = isSumOf(s, n, i + 1, sum, builder); // try to skip "s[i]" and instead to sum "s[i+1]"
    
        return with || without;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 2015-10-31
      相关资源
      最近更新 更多