【问题标题】:How to solve a problem with ArrayLists recursively如何递归地解决 ArrayLists 的问题
【发布时间】:2019-08-16 08:02:18
【问题描述】:

我正在尝试编写一个“解圆”的程序。 Circle 类包含一个三角形对象的 ArrayList 和一个整数的 ArrayList。每个 Triangle 对象都有三个 int 实例字段,它们代表每个三角形顶点处的三个数字。还有一个 Pairs 类(你可以在“代码”部分看到我所有的代码) 以下是使用四个未求解的三角形的设置示例:

这是“解决”后的同一个圆圈:

第二张图中的Circle是一个求解过的Circle,因为圆的任意弧上的数都等于它旁边的两个顶点数之和:6 = 1+5, 15 = 6+9, 11 = 7+4,9 = 5+4。请注意,这是通过旋转给定的三角形获得的。这在代码中类似于简单地更改每个三角形的解决方案中存在的 Pair(其中“Pair”是两个整数的对象,其中这些整数是每个三角形的圆上的值)

圆并不总是处于“已解决”状态。如果是这种情况,可以旋转三角形,使圆处于求解状态。任何给定圆的前提是存在已解决的状态,因此数字将始终对齐。

一个圆总是至少有两个三角形,并且没有(实际的)最大数量。每个给定的圆总是可解的,这意味着有一种方法可以旋转每个三角形,以便圆上的数字是两个不同三角形的两个相邻顶点之和的结果。

程序的重点是不改变任何给定的实例字段;相反,我只想创建一个名为 solveCircle 的方法,它返回一个 ArrayList of Pairs,表示圆的解决方案。在上面的示例中,solveCircle 方法将返回一个包含以下对的 ArrayList:(4,1)、(5,6)、(9,7)、(4,5)。这些对在解决方案中,因为它们都是三角形上的数字对,并且每一对也在圆上。请注意,解决方案是围绕圆圈逆时针旋转的。

我的直觉告诉我,这个过程应该涉及某种类型的递归,因为由于循环的循环性质,循环会很棘手;换句话说,我可以遍历每一对三角形以找到合适的解决方案,但很可能不止一个,并且将每个三角形与下一个总和的解决方案进行比较似乎效率低下;递归似乎是一个更好的选择,但我不确定将递归应用于什么......我应该使用什么算法,甚至是什么基本情况?

public class Triangle
{
    private int num1;
    private int num2;
    private int num3;

    public Triangle(int n1, int n2, int n3)
    {
        num1 = n1;
        num2 = n2;
        num3 = n3;
    }

    public ArrayList<Pair> getPairs()
    {
        ArrayList<Pair> pairs = new ArrayList<Pair>();
        pairs.add(new Pair(num1, num2));
        pairs.add(new Pair(num2, num3));
        pairs.add(new Pair(num3, num1));
        return pairs;
    }
}
class Pair
{
    private int p1;
    private int p2;

    public Pair(int x, int y)
    {
        p1 = x;
        p2 = y;
    }
}
public class Circle
{
    private ArrayList<Triangle> triangles;
    private ArrayList<Integer> sums;

    public Wheel(ArrayList<Integer> s, ArrayList<Triangle> t)
    {
        triangles = t;
        sums = s;
    }

    public ArrayList<Pair> solveCircle()
    {
        //need help here
    }
}

【问题讨论】:

  • “逆时针”,但哪个先出现:三角形 0 还是总和 0?
  • 三角形 0 会先出现,所以我会使用三角形 0 和三角形 1 来求和 1,依此类推,直到找到三角形“size()-1”。然后我会使用它和 Triangle 0 和 sum 0。sum ArrayList 的大小将比 Triangle ArrayList 的大小小一。
  • 我会使用数独方法。绕过圆圈并找到具有最少有效方向数的三角形。如果只有一个有效方向,请选择该方向并锁定三角形。如果有两个或三个有效方向,则选择一个,然后递归。
  • 我认为我的问题是,当递归的概念不用于数字序列或阶乘或总和等情况时,我对递归的概念感到困惑。在这种情况下,我不太确定递归是什么。我将如何编写基本案例?我想我只需要一个例子来说明它是如何工作的,例如,在我作为例子给出的 4-triangle Circle 中。
  • 我会在Triangle 类中添加一个state 变量。有两种状态:UndecidedLocked。在递归的每一级,一个三角形被分配一个方向,并被锁定。这意味着在每个递归级别上,都会少一个未定三角形。成功的基本情况:所有三角形都被锁定。否则,找到一个具有最少有效方向的未定三角形。为该三角形选择一个方向,锁定它,然后递归。请注意,可能存在没有有效方向的未定三角形。这是失败的基本情况。

标签: java algorithm recursion


【解决方案1】:

对于初始步骤,您调用帮助程序 3 次:每对调用一次,直到返回成功(布尔值可用于指示成功。)

助手执行递归步骤。

对于递归步骤,你有一个在你身后延伸的总和,一个你必须结合起来才能满足该总和的整数,以及实现它的三种可能方法......但是除非你的递归调用也返回,否则你不会返回成功成功

对于最后一步,不允许旋转,只是最后的真假我是否完成了我身后的总和。

【讨论】:

  • 所以我的辅助函数是一个布尔函数,如果两个顶点的总和等于我想要的总和,则返回 true?我对你的解释有点迷茫(也许是因为我无法将其想象为递归,就像斐波那契数是递归的一样)。我很抱歉没有及时回复;我试图在没有递归的情况下自己做这件事。我想出了一些东西,但它很乱,不幸的是,它没有输出正确的答案。
  • 如果它的当前旋转与它后面所需的总和匹配,并且递归调用也为真,则辅助函数返回 true 否则它会尝试下一次旋转,直到它尝试了所有三个然后它返回 false
【解决方案2】:

您可以使用tree 将已求解的三角形与未求解的三角形分开。对于已解决和未解决的圆圈也是如此。这样,您可以将其设为 log n 搜索函数,该函数将忽略已解决的问题,从而避免不必要的比较。

if (solved)
    add to left side of the tree
else 
    add to right side of the tree

根据用例的不同,这也可能过于复杂。

【讨论】:

  • 我在课堂上还没有学过树,我不能使用任何没有使用过的东西。我不明白您所说的“已解决的三角形”是什么意思。除非正确求解整个圆,否则我不知道三角形是否正确。例如,如果总和为 10,并且我有两个相邻的三角形,其顶点分别为 3、4、8 和 7、6、2,那么将有三种不同的排列方式是正确的;但只有一个会根据圆圈中的其他信息工作,即其他总和和其他三角形。
  • 编辑您的问题,并提供更多关于如何接收问题的示例。例如,据此,我无法理解圆的最大大小,以及问题存在的值的域/范围是什么。
  • 这就是为什么我认为它与递归有关,我会检查两个三角形是否正确,然后检查第三个三角形是否有效,如果它确实继续第四个,但如果没有,请返回并重新访问前两个三角形。我只是不确定如何实现它。
  • 编辑了一个“给定”圆的例子,然后是解决的版本。我需要编写代码来获取给定的 Circle,然后生成一个 ArrayList of Pairs,它表示作为解决方案一部分的每个三角形的顶点对。
  • 我认为这个答案不正确。三角形不是孤立地“解决”的。它可能需要再次旋转,具体取决于稍后发生的情况。
猜你喜欢
  • 2020-03-26
  • 2020-06-30
  • 2022-01-10
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-11
  • 2022-01-25
相关资源
最近更新 更多