【问题标题】:Java: check if arraylist is part of fibonacci sequenceJava:检查arraylist是否是斐波那契数列的一部分
【发布时间】:2016-09-03 06:48:57
【问题描述】:

我的学校任务是实现一个方法来检查给定的ArrayList 是否是斐波那契数列的一部分。

数组不能为空,且必须大于3。

我知道我必须检查数组的一个数字和下一个数字是否是斐波那契数列的一部分,但是我有很多麻烦,因为如果它是数组的任何一部分,你应该接受它顺序,而不仅仅是从一开始。

例如:0 1 1 2 3 52 3 5 8 13 21 将被接受。

到目前为止,这是我的代码。我知道它有很大的缺陷,但我真的不知道如何继续。

public class ArrayCheck {
 /**
 * Tests if the given array is a part of the Fibonacci sequence.
 *
 * @param arr array to be tested
 * @return true if the elements are part of the fibonacci sequence
 */
public boolean isFibonacci(ArrayList<Integer> arr) {
    //check if array exists
    if(arr.size() == 0)
        return false;

    //check if array is bigger than 3
    if (arr.size() < 3)
        return false;

    //check for the startsequence of 0,1,1
    else if(arr.get(0) == 0 && arr.get(1) == 1 && arr.get(2) == 1)
        return true;

    //check every number in array
    for(int i = 0; i < arr.size(); i++) {
        //check if i >= 2 is fib
        if(i >= 2) {
            int fibn = i;
            int nextfib = i + 1;

            int fibnew = (fibn - 1) + (fibn - 2);
            int fibnext = (nextfib - 1) + (nextfib - 2);

            if (arr.get(i) != fibnew && arr.get(i + 1) != fibnext)
                return false;
        }
        //check if the order is right
        if(arr.get(i) > arr.get(i+1))
            return false;
    }
    return true;
}

非常感谢任何帮助!

【问题讨论】:

    标签: java arraylist fibonacci


    【解决方案1】:

    好吧,您的代码存在一些问题。首先,如果您的数组至少有 3 个项目,则检查是否只有前三个是斐波那契数列的开始:

    //check for the startsequence of 0,1,1
    else if(arr.get(0)==0 && arr.get(1)==1 && arr.get(2)==1){
        return true;
    }
    

    这很糟糕,因为这意味着不属于序列的0 1 1 5 将返回 true。

    你需要做的是把它分成两个任务:

    • 在序列中找到第一个相关的数字(即如果数组以7 开头,你知道这不是序列的一部分;或者,如果它以8 开头,你知道你需要开始从8 开始检查)。
    • 找到“开始”后,只需检查数组的其余部分是否符合斐波那契规则。您需要手动验证前两项。

    public boolean isFibonacci(ArrayList<Integer> arr) {
    
        if (arr.size() < 3){
            return false;
        }
    
        /** find if the first element is part of the sequence: **/
    
        int fib1 = 0;
        int fib2 = 1;
    
        while (fib1 < arr.get(0)) {
            int tmp = fib1 + fib2;
            fib1 = fib2;
            fib2 = tmp;
        }
    
        if (fib1 != arr.get(0)) {
            // first element is not part of Fibonacci sequence
            return false;
        }
    
        if (fib2 != arr.get(1)) {
           // the first two elements are not part of the Fibonacci sequence
           return false;
        }
    
        /*** now simply verify that the rest of the elements uphold the rule:
             each element is the sum of the two previous ones: **/
    
        for(int i=2; i < arr.size(); i++) {
    
            // make sure there are no negatives in the array:
            if (arr.get(i) < 0)
               return false;
    
            if (arr.get(i) != (arr.get(i-1) + arr.get(i-2)))
               return false;
    
        }
    
        //everything checks out okay - return true:
        return true;
    }
    

    【讨论】:

    • 其实不需要检查负数。第一个负值,如果存在于数组中,前面至少有两个正数——这违反了求和约束(没有这样的两个数字 > 0 和
    • 你是对的。我过于谨慎了。谢谢你:)
    • 你测试过这个实现吗?
    • 实际上,在我实现它之后,我运行了一些 junit 测试,对于实际的斐波那契序列,它不会返回 true,其他一切正常。但是,在更改此行while (fib1 &lt;= arr.get(0)) { to while (fib1 &lt; arr.get(0)) { 后,我没有更多错误
    • 因为,正如我“暗示”的那样……它不起作用。特别是在第一个while 完成时,fib1 != arr.get(0)始终为真,这会导致自动返回 false。代码完全错误。
    【解决方案2】:
    private boolean isFib(final List<Integer> li) {
        //check if each int is the sum of the two prior ints
        for (int i = 2; i < li.size(); i++) {
            if (li.get(i) != li.get(i - 1) + li.get(i - 2)) {
                return false;
            }
        }
    
        //reverse the fibonacci sequence and check if we end up at the correct starting point (0, 1)
        int i1 = li.get(0);
        int i2 = li.get(1);
    
        while (i1 > 0) {
            final int tmp = i1;
            i1 = i2 - i1;
            i2 = tmp;
        }
    
        return i1 == 0 && i2 == 1;
    }
    

    【讨论】:

    • 不,因为2, 2, 4, 6 不是斐波那契序列的一部分。
    • 那么你接受这个:[2 2 4 6 10] 这不是斐波那契的一部分。
    • 修复它,检查第一个数字。或不。重点是从索引 2 开始的循环..
    • 这是一个有效的斐波那契吗? [0 5 5 10]
    • 如果情况下,那将由警卫照顾。
    【解决方案3】:

    我建议一个解决方案,在单独的Iterator&lt;Integer&gt; 中抽象斐波那契序列生成器,然后使用它来检查提供的列表是否与序列的任何部分匹配。

    迭代器非常简单明了:

    public static class FiboIterator implements Iterator<Integer> {
    
        @Override
        public boolean hasNext() { return true; }
    
        int i = -1, j = -1;   // previous two items of Fibo sequence
    
        @Override
        public Integer next() {
            int k = (i < 0) ? (j < 0 ? 0 : 1) : (i + j);
            i = j;
            j = k;
            return k;
        }
    }
    

    主要检查方法:

    public static boolean isFibo(List<Integer> seq) {
        if (seq.size() < 3)
            return false;
        final Iterator<Integer> f = new FiboIterator();
        int start = seq.get(0), k;
        while ((k = f.next()) < start);         // roll Fibo to match the starting item in input
        if (start != k)                         // starting item doesn't match
            return false;
        if (start == 1 && seq.get(1) != 1)      // special case: [1, 2, ...]
            f.next(); 
        for (int i = 1; i < seq.size(); i++) {  // check if other items match
            if (seq.get(i) != f.next())
                return false;
        }
        return true;
    }
    

    最后是一些单元测试:

    @Test
    public void testFibo() {
        assertTrue(isFibo(Arrays.asList(0, 1, 1, 2)));
        assertTrue(isFibo(Arrays.asList(1, 1, 2, 3, 5)));
        assertTrue(isFibo(Arrays.asList(1, 2, 3, 5, 8)));
        assertTrue(isFibo(Arrays.asList(5, 8, 13, 21, 34)));
    
        assertFalse(isFibo(Arrays.asList(1, 2, 0)));
        assertFalse(isFibo(Arrays.asList(1, 0, 1)));
        assertFalse(isFibo(Arrays.asList(5, 5, 10, 15)));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-23
      • 2015-08-30
      • 1970-01-01
      • 2014-03-15
      • 2012-11-09
      • 2011-01-26
      • 1970-01-01
      • 2017-03-31
      相关资源
      最近更新 更多