自定义LinkedList:选择备用整数元素

时间:2016-04-23 16:01:25

标签: java list recursion

我有一个Integer [21, 9, 13, 47, 5, 10, 19, 36, 20, 11, 13]的列表,我正在尝试编写一个递归函数,它将返回原始列表中的每个其他整数作为列表
(即{{1 }})。

我正在使用LispList的自定义实现。该对象称为 LispList ,它是不可变的并且(显然)未编入索引。它提供了以下方法:

E head() - 返回调用它的列表的第一项 LispList< E> tail() - 返回一个新列表,该列表除了调用它的列表的第一项外都包含 LispList< E> cons(E item) - 接受一个参数并返回一个新的列表,其头部是参数,其尾部是调用它的列表。
boolean isEmpty() - 如果调用它的列表是空列表,则返回true,否则返回false。 静态< T> LispList< T> empty() - 返回一个空列表。

经过几个小时的尝试后,我想出了一种方法,我使用一个初始化为2的计数器并使用它来跟踪偶数编号的元素,这些元素应该被挑出并放入一个新的LispList并返回。

但是,当我运行代码时,它会抛出NullPointerException而我看不清楚原因。也许我刚刚盯着屏幕看了太久!

这是从[21, 13, 5, 19, 20, 13]调用的方法:

main


辅助方法:

public static <T> LispList<T> pickEveryOther(LispList<T> ls) {
        int counter = 2; 
        LispList<T> ls1 = pickEveryOtherHelper(ls.tail(), counter);
        return ls1;
}

非常感谢您的努力。

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题,只需抓住头部,然后尝试将尾巴拉两次并对其进行处理。只是说明它可以在每个尾部之后成为一个空列表。然后将头部添加到递归的结果中。

public static <T> LispList<T> everyOther(LispList<T> lispList) {
    if (lispList.isEmpty()) {
        return lispList.empty();
    }
    T head = lispList.head();
    LispList<T> tail = lispList.tail();
    if (!tail.isEmpty()) {
        tail = tail.tail();
    }
    tail = everyOther(tail);
    return tail.cons(head);
}

答案 1 :(得分:1)

解决方案是在每次递归时从列表中弹出2个值,并使用2个值之一构建新列表。

你没有真正说明“每隔一个”是指第1,第3,第5,......还是第2,第4,第6 ......,所以这里有两个解决方案。

public static <T> LispList<T> pickOdd(LispList<T> ls) {
    if (ls.isEmpty())
        return ls; // return empty
    LispList<T> tail1 = ls.tail();
    if (tail1.isEmpty())
        return ls; // return of(ls.head())
    LispList<T> tail2 = tail1.tail();
    if (tail2.isEmpty())
        return tail2.cons(ls.head()); // return of(ls.head())
    return pickOdd(tail2).cons(ls.head());
}
public static <T> LispList<T> pickEven(LispList<T> ls) {
    if (ls.isEmpty())
        return ls; // return empty
    LispList<T> tail1 = ls.tail();
    if (tail1.isEmpty())
        return tail1; // return empty
    LispList<T> tail2 = tail1.tail();
    if (tail2.isEmpty())
        return tail1; // return of(ls.tail().head())
    return pickEven(tail2).cons(tail1.head());
}

为了测试它,我确实实现了LispList,有两个辅助方法(of(...)toString()):

final class LispList<E> {
    private final E           head;
    private final LispList<E> tail;
    private LispList(E head, LispList<E> tail) {
        this.head = head;
        this.tail = tail;
    }

    /** returns the first item of the list it is called on */
    public E head() {
        if (isEmpty()) throw new IllegalStateException();
        return this.head;
    }
    /** returns a new list consisting of all but the first item of the list it is called on */
    public LispList<E> tail() {
        if (isEmpty()) throw new IllegalStateException();
        return this.tail;
    }
    /** takes an argument and returns a new list whose head is the argument and whose tail is the list it is called on */
    public LispList<E> cons(E item) {
        return new LispList<>(item, this);
    }
    /** returns true if the list it is called on is the empty list, returns false otherwise */
    public boolean isEmpty() {
        return this.tail == null;
    }
    /** returns an empty list */
    public static <T> LispList<T> empty() {
        return new LispList<>(null, null);
    }

    @SafeVarargs
    public static <T> LispList<T> of(T ... values) {
        LispList<T> ls = empty();
        for (int i = values.length - 1; i >= 0; i--)
            ls = ls.cons(values[i]);
        return ls;
    }
    @Override
    public String toString() {
        StringJoiner joiner = new StringJoiner(", ", "[", "]");
        for (LispList<E> ls = this; ! ls.isEmpty(); ls = ls.tail())
            joiner.add(String.valueOf(ls.head()));
        return joiner.toString();
    }
}

<强> TEST

LispList<Integer> ls = LispList.of(21, 9, 13, 47, 5, 10, 19, 36, 20, 11, 13);
System.out.println("List: " + ls);
System.out.println("Odd : " + pickOdd(ls));
System.out.println("Even: " + pickEven(ls));

<强>输出

List: [21, 9, 13, 47, 5, 10, 19, 36, 20, 11, 13]
Odd : [21, 13, 5, 19, 20, 13]
Even: [9, 47, 10, 36, 11]