我的学校任务是实现一种方法,检查给定的ArrayList
是否属于Fibonacci序列。
数组不能为空,且必须大于3。
我明白我必须检查数组中的一个数字和下一个数字是Fibonacci序列的一部分,但是我有很多麻烦因为你应该接受数组,如果它是任何一部分顺序,而不仅仅是从一开始。
例如:0 1 1 2 3 5
将被接受以及2 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;
}
非常感谢任何帮助!
答案 0 :(得分:2)
嗯,您的代码存在一些问题。首先,如果数组至少有3个项,那么检查前三个是否只是Fibonacci序列的开头:
//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;
}
答案 1 :(得分:1)
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 :(得分:0)
我建议使用一个解决方案,在单独的Iterator<Integer>
中提取Fibonacci序列生成器,然后使用它来检查提供的列表是否与序列的任何部分匹配。
Iterator非常简单直接:
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)));
}