Java 递归平方划分
我在理解递归方面有困难,无法解决以下问题 输入:一个对象(f.e.字段)和整数n 所需输出:包含n个字段的列表 我写了一个方法,它把一个简单的对象分成两部分,效果很好。但我无法处理递归 createFields(字段,5)的最小示例: 你能帮我做这个吗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
谢谢大家! 算法的高级描述是:
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