在不断缩小的LispList中递归地查找INT的索引

时间:2014-10-18 16:16:07

标签: java recursion arraylist lisp

这里的二年级计算机科学专业学生,作为一系列递归练习的一部分,我们已经给了一些用LispLists解决的任意问题。我被困在中途,所以如果有人能指出我正确的方向而没有明确地给我答案,那就太好了。

我需要在LispList listToCheck 中找到 intToFind 的每个实例的位置 - 唯一的条件那是:

  • 无法使用其他参数
  • 必须以递归方式完成

对于没有遇到过LispLists的人 - 他们没有索引,你可以调用的唯一方法是:

  • .isEmpty() 返回布尔值
  • .head() 返回第0位的元素
  • .tail() 返回不是头部的所有元素的LispList
  • .cons(价值) 为' head'增添价值。位置 - 将其他一切转移到

我之前写的一种方法也叫做:

  • recursiveCountLength(list) 返回传递的LispList长度的int。

我正在测试的列表是: [2,3,4,2,5,12,2,5] ,所以结果我正在寻找是 [0,3,6] - 顺便说一句,这是我到目前为止所得到的(解释我之后尝试的事情):< / p>

public static LispList<Integer>
  recursivePositions(LispList<Integer> listToCheck, int intToFind)
{
  if(listToCheck.isEmpty()) return listToCheck;
  else {
    // go through the array in its entirety once through,
    // do everything else 'on the way back up'
    LispList<Integer> positions = recursivePositions(listToCheck.tail(), intToFind);

    //get the current length and current head
    int currentInt      = listToCheck.head();
    int currentLength   = recursiveCountLength(listToCheck); 

    //if a match is found, add the current length of the list to the list 
    if(currentInt == intToFind) return positions.cons(currentLength);
    else return positions;
  }
}

我目前的理论是,在列表的原始长度(在这种情况下为8)中减去我们要查找的int(在这种情况下为2)的每次遇到时数组的长度将为我们提供索引

  • 2 首先发生长度为8(8-8 =索引为0,因此索引为[0]),
  • 2 接下来发生的长度为5(8-5 =索引为3,所以索引现在为[0,3]),
  • 2 最后发生在2的长度(8-2 =索引为6,因此索引现在为[0,3,6])。

唯一的问题是,我无法弄清楚如何获得静电&#39; 8&#39; - 这使我得出结论,我完全以错误的方式接近这一点。有人在这里有任何提示吗?任何帮助都将非常感激。

2 个答案:

答案 0 :(得分:1)

澄清:LispList只是一个单链接列表(以区别于双链接的Java LinkedList。)

通常,您会使用一个帮助程序将信息传递到递归调用中,例如当前位置和已找到的位置(当前部分结果)。

LispList<Integer> positions (final int item, final LispList<Integer> list) {
    return positionsAux( item, list, 0, new LispList<Integer>() );
}

private LispList<Integer> positionsAux (final int item,
                                        final LispList<Integer> list,
                                        final int position,
                                        final LispList<Integer> result) {
    if (list.isEmpty()) {
        return result.reverse();
    }
    if (list.head().intValue() == item) {
        result = result.cons(position);
    }
    return positionsAux( item, list.tail(), position + 1, result );
}

如果不允许,您需要向后传递结果。如果您认为递归调用已为您的list.tail()返回了正确的结果,则需要为每个找到的位置添加1以获得list的正确结果。然后,如果当前元素匹配,则cons为0。此版本的效率低于第一个版本,因为您遍历输入列表的每个元素的当前结果列表(因此它是 O(n·m)而不是 O(n)< / em>,其中 n 是输入列表的长度, m 是结果列表的长度。)

LispList<Integer> positions (final int item, final LispList<Integer> list) {
    if (list.isEmpty()) {
        return new LispList<Integer>();
    }
    final LispList<Integer> tailResult = positions( item, list.tail() );
    final LispList<Integer> result = tailResult.addToEach( 1 );
    if (list.head().intValue() == item) {
        return result.cons( 0 );
    } else {
        return result;
    }
}

为第一个版本实施reverse(),为第二个版本实施addToEach(int)作为练习留给读者。

答案 1 :(得分:0)

您至少需要3个参数。非常确定添加更多参数是可以的,因为他允许帮助方法(因为否则你可以让你的方法调用具有更多参数的辅助方法)。

递归最简单的方法:

public static LispList<Integer> positions(LispList<Integer> list, Integer key, Integer position){
    if (list.isEmpty()) return  LispList.empty();

    if (list.head().equals(key)) return positions(list.tail(), key, position+1).cons(position);

    return positions(list.tail(), key, position+1);
}