Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 递归平方划分_Java_Algorithm_Math_Recursion - Fatal编程技术网

Java 递归平方划分

Java 递归平方划分,java,algorithm,math,recursion,Java,Algorithm,Math,Recursion,我在理解递归方面有困难,无法解决以下问题 输入:一个对象(f.e.字段)和整数n 所需输出:包含n个字段的列表 我写了一个方法,它把一个简单的对象分成两部分,效果很好。但我无法处理递归 createFields(字段,5)的最小示例: 你能帮我做这个吗 谢谢大家! 算法的高级描述是: divide_recursively (fields, n) args: input/output fields : List of fields input n : integer (number

我在理解递归方面有困难,无法解决以下问题

输入:一个对象(f.e.字段)和整数n

所需输出:包含n个字段的列表

我写了一个方法,它把一个简单的对象分成两部分,效果很好。但我无法处理递归

createFields(字段,5)的最小示例:

你能帮我做这个吗


谢谢大家!

算法的高级描述是:

divide_recursively (fields, n)
args:
    input/output fields : List of fields
    input n : integer (number of fields)
precondition:
    head of list is largest available field
body:
    if (fields.size() == n) return
    f = fields.front()
    fields.pop_front()
    fsplit[] = split_field(f)
    fields.push_back(fsplit[0])
    fields.push_back(fsplit[1])
    divide_recursively(fields, n)
只要
split_field
将输入精确地分成两半,该算法始终满足前提条件

该算法是使用递归提出的,因为递归是问题中的一个标记。这使用尾部递归,许多编译器/解释器将其转换为常规循环作为优化的特例


上面的算法使用贪婪的方法。下面是一个使用分而治之方法的替代算法

divide_recursively (fields, n)
precondition:
    fields contains exactly one element
body:
    if (n == 1) return
    f = fields.front()
    fields.pop_front()
    fpslit[] = split_field(f)
    subfields1 = new list + fsplit[0]
    subfields2 = new list + fsplit[1]
    divide_recursively(subfields1, n/2)
    divide recursively(subfields2, n - n/2)
    fields = subfields1 + subfields2

您应该能够迭代地使用当前函数。从1个字段开始,调用函数,该函数给出了2个字段的列表。将这些添加到临时列表中。现在只需在这些字段上调用split函数。一旦您用完了一定大小的字段,您可以从拆分较小的字段开始

下面的代码应该为您提供n个大小为x和x/2的字段(存储在
字段
字段2中)

Field startField=...
ArrayList<Field> fields=new ArrayList<Field>();
ArrayList<Field> fields2=new ArrayList<Field>();
fields.add(startField);
nrFields=1;
outerlabel:
while(nrFields<n){
    while((!fields.isEmpty()){
        Field fieldToSplit = fields.remove(0);
        List<Field> splitFields=splitt(fieldToSplit);
        fields2.addAll(splitFields);
        nrFields++;
        if(nrFields==n)break outerlabel;
    }
    fields=fields2;
    fields2=new ArrayList<Field>();

}
字段开始字段=。。。
ArrayList字段=新的ArrayList();
ArrayList fields2=新的ArrayList();
字段。添加(startField);
nrFields=1;
外标签:

(nrFields在我的一个评论之后,这里是一个非递归解决方案的建议(伪代码):

split(字段,n){
队列=新队列()
queue.addLast(字段)
while(queue.size()

}

字段的大小有限制吗?我觉得您不需要1/5、1/4、1/8和2/16。问题没有很好的定义。什么是“字段”?是否只允许在一次操作中将其分成两个相等的部分?N是否可以是一个不同于2的幂的值?是的。5是一个不同于2的幂的值。字段是一组点*。我想要一个近似相等的“字段”。谢谢。如果您每次只想分割最大的字段,直到达到所需的字段数,那么这实际上是一个呼吸优先搜索,递归不适合。很好!但是,这个尾部递归可以很容易地转换为循环。我看不出这个问题陈述中递归的意义。@EyalScheider可以你给我举个例子吗?谢谢!@EyalSchneider:我同意,但编译器可以帮你这么做。@uccie:如果你需要使用递归,那么这肯定是一个有效的解决方案。但是你可以简单地循环,直到集合的大小为n,然后返回集合。实际上,这个集合应该是一个堆,以允许检索最大的e很容易删除。@uccie:我自己更正了;集合不需要是堆。它足以将新元素一直推到列表的末尾。它实际上是一个队列。你可以在另一个答案中看到我的非递归建议。
Field startField=...
ArrayList<Field> fields=new ArrayList<Field>();
ArrayList<Field> fields2=new ArrayList<Field>();
fields.add(startField);
nrFields=1;
outerlabel:
while(nrFields<n){
    while((!fields.isEmpty()){
        Field fieldToSplit = fields.remove(0);
        List<Field> splitFields=splitt(fieldToSplit);
        fields2.addAll(splitFields);
        nrFields++;
        if(nrFields==n)break outerlabel;
    }
    fields=fields2;
    fields2=new ArrayList<Field>();

}
split(field, n) {
    queue = new Queue()
    queue.addLast(field)
    while (queue.size() < n) {
        f = queue.removeFirst()
        pair = f.split()
        queue.addLast(pair.a)
        queue.addLast(pair.b)
    }
    return queue