递归方形分区

时间:2013-03-14 21:47:15

标签: java algorithm math recursion

我在理解递归方面遇到了麻烦,我无法解决以下问题。

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

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

我编写了一个方法,它将一个简单的对象分成两部分,并且工作正常。但我无法处理递归。

createFields(field,5)的最小示例:

Input:
**********************************
*                                *
*                                *
*                                *
**********************************
1st iteration (after divide(field))
**********************************
*                *               *                
*                *               *
*                *               *
**********************************
2nd iteration 
**********************************
*                *               *                
**********************************
*                *               *
**********************************
3rd last iteration 
**********************************
*       *        *               *                
**********************************
*                *               *
**********************************

你能帮我解决这个问题吗?

谢谢!

3 个答案:

答案 0 :(得分:0)

算法的高级描述是:

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将输入分成两半,就可以在此算法中满足前提条件。

使用递归来呈现算法,因为这是问题中的标记之一。这使用尾递归,许多编译器/解释器将转换为常规循环作为tail call优化的特殊情况。


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

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 :(得分:0)

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

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

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>();

}

答案 2 :(得分:0)

根据我的一条评论,这是一个非递归解决方案的提案(伪代码):

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

}