【问题标题】:Recursion and While Loops in JavaJava 中的递归和 While 循环
【发布时间】:2020-06-28 01:29:36
【问题描述】:

我正在写一个递归程序:

public static List<Integer> method(int n)

确定正数n 是否是正数立方体的总和 (> 0)。示例:给定n = 1944 (12^3 + 6^3),程序将按降序返回列表[12, 6]。如果n 不是立方体的总数,程序应该返回一个空列表。

程序应该为第一个元素返回从最高可能值开始的值,然后对其余元素遵循相同的规则。比如n = 1072,程序会返回[10, 4, 2]而不是[9, 7]

递归应该发生的方法:

private static boolean method(int n, int c, LinkedList<Integer> seen)

其中c 是仍然允许使用的最高号码,soFar 是已经看到的号码列表。

我的代码涵盖了基本情况和递归,但我在循环继续时遇到了问题。通过输入,n = 1944 我的程序将返回列表 [12] 而不是 [12, 6]

    public static List<Integer> method(int n)
    {
        LinkedList<Integer> result = new LinkedList<Integer>();
        int c = (int) Math.cbrt(n);
        result.add(c);
        method(n, c, result);
        return result;
    }
    private static boolean method(int n, int c, LinkedList<Integer> seen)
    {
        LinkedList<Integer> result = new LinkedList<Integer>();
        boolean b = false;
        if (n == 0)
        {
          return true;  
        }
        else if (c == 0)
        {
            return false;
        }
        else 
        {
            int sum = 0;
            for (int i : seen)
            {
                sum += i*i*i;
            }
            while (b = false)
            {
                c = (int) Math.cbrt(n - sum);
                seen.add(c);
                method(n, c, seen);
                if (sum == n)
                {
                    result = seen;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        return false;
    }


【问题讨论】:

  • j^3 不是 j 立方,它是 j bitwise-exclusive-OR 3
  • 艾略特,10^3 + 4^3 + 2^3 = 1072
  • 请停止删除和转发您的问题。这在 SO 上是不允许的。如果您没有得到答案,请考虑改进它和/或为问题设置奖励。
  • 抱歉,不知道如何设置赏金或这意味着什么。我也只是认为人们没有看到这个问题,这就是原因。没有收到太多反馈,谢谢
  • 这是因为你的问题很难理解。在您的解释中,您声明一个数字等于 12 立方 + 6 立方,并且返回值应该是列表 [11, 2] 为什么是 11,而不是 12?正是这样的事情让我以前每次看到它都会错过它。

标签: java recursion while-loop linked-list boolean


【解决方案1】:

让我们看看你的 while 循环:

LinkedList<Integer> result = new LinkedList<Integer>();
boolean b = false;
// Some code omitted here.
while (b = false)
{
    c = (int) Math.cbrt(n - sum);
    seen.add(c);
    method(n, c, seen);
    if (sum == n)
    {
        result = seen;
        return true;
    }
    else
    {
        return false;
    }
}

首先,对于一个始终以false 作为循环条件的while 循环,它根本不做任何事情。

无论如何,即使我们假装循环运行,无论if 采用的分支是什么,return 都会到达。因此,您的while 循环根本不会循环,即使它的条件更改为始终为true。此外,曾经为b 变量分配的唯一值是false,它根本不用于任何事情。

另外,第二种方法中的result 列表始终为空。而且,由于result = seen; 指令正好在return 之前,它是一个无害的指令,它使result 根本无用。

另外,请查看method(n, c, seen); 电话。它不会对其返回值做任何事情!因此,即使它最终返回 true,您仍会继续,然后会生成 false 作为结果。

此外,每当您向seen 添加值时,它都不会被删除。由于 seen 在每个递归方法调用中始终是同一个列表,因此一旦在其中添加了错误的数字,就永远不会将其删除以为其他内容腾出空间。

有了这个,我必须得出结论,你的算法非常糟糕,必须从头开始重写。

另外,虽然你的问题不是很清楚,但我认为找到的数字肯定是不同的。否则,可以得到2 = 1<sup>3</sup> + 1<sup>3</sup>,并且每个大于一的数字都可以用许多立方数的和来表示(即n = 1<sup>3</sup> + 1<sup>3</sup> + 1<sup>3</sup> + ...)。

算法是这样的:

  • 第一步是让for 计数icbrt(n) 减少到1 试图形成立方体。
  • 然后,从n 中减去立方并递归地尝试找到结果数的立方和。
  • 添加一个参数以避免重复数字,该参数比最后使用的数字小一。
  • 当一个立方体形成时,返回形成它的数字。在外部调用中,将结果添加到非空内部递归调用列表中。
  • 如果内部递归调用结果是一个空列表,那么 for 的当前迭代产生了一个错误的数字,我们应该尝试下一个(如果我们有下一个)。
  • 如果 for 结束时没有形成立方体,则返回一个空列表。

代码如下:

import java.util.LinkedList;
import java.util.List;

public class Main {
    public static List<Integer> findCubeSum(int n) {
        return findCubeSum(n, n);
    }

    public static List<Integer> findCubeSum(int n, int max) {
        if (n <= 0) return List.of();
        int c = (int) Math.cbrt(n);
        for (int i = Math.min(c, max); i > 0; i--) {
            int x = i * i * i;
            if (x == n) {
                List<Integer> result = new LinkedList<>();
                result.add(i);
                return result;
            }
            List<Integer> result = findCubeSum(n - x, i - 1);
            if (result.isEmpty()) continue;
            result.add(0, i);
            return result;
        }
        return List.of();
    }

    public static void main(String[] args) {
        System.out.println(findCubeSum(8));    // [2]
        System.out.println(findCubeSum(64));   // [4]
        System.out.println(findCubeSum(1000)); // [10]
        System.out.println(findCubeSum(1072)); // [10, 4, 2]
        System.out.println(findCubeSum(1944)); // [12, 6]
        System.out.println(findCubeSum(4));    // []
        System.out.println(findCubeSum(0));    // []
        System.out.println(findCubeSum(-1));   // []
        System.out.println(findCubeSum(10));   // []
    }
}

ideone查看它的运行情况。

【讨论】:

  • 程序必须计算所有不同的数字,你是对的。当给出例如 n = 1000 时,它不能只返回立方根 (10),它需要找到总 n 的数字。它还需要维护方法声明。
  • @Roozilla 所以即使n 本身就是一个完美的立方体,它也必须至少是两个不同的数字?
【解决方案2】:

发布的代码有很多问题。但是你的问题是关于public static List&lt;Integer&gt; method(int n)

public static List<Integer> method(int n)  {
    LinkedList<Integer> seen = new LinkedList<>();
    method(n, 0, seen);
    return seen;
}

考虑改变

private static boolean method(int n, int c, LinkedList&lt;Integer&gt; seen)

private static boolean method(int n, LinkedList&lt;Integer&gt; seen)

因为你用c = (int) Math.cbrt(n);重新计算了c的值

【讨论】:

    猜你喜欢
    • 2012-08-04
    • 2016-03-19
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 2013-09-30
    • 1970-01-01
    相关资源
    最近更新 更多