Trình tự Fibros đệ quy Java


156

Vui lòng giải thích mã đơn giản này:

public int fibonacci(int n)  {
    if(n == 0)
        return 0;
    else if(n == 1)
      return 1;
   else
      return fibonacci(n - 1) + fibonacci(n - 2);
}

Tôi bối rối với dòng cuối cùng đặc biệt bởi vì nếu n = 5 chẳng hạn, thì Wikipedia (4) + Dailymotion (3) sẽ được gọi và v.v. nhưng tôi không hiểu thuật toán này tính toán giá trị ở chỉ số 5 bằng cách nào phương pháp. Hãy giải thích với rất nhiều chi tiết!


8
Lưu ý rằng đây là đệ quy và chạy trong thời gian theo cấp số nhân. Nó không hiệu quả đối với các giá trị lớn của N. Sử dụng phương pháp lặp tôi có thể tính 10.000 số đầu tiên trong chuỗi. Chúng có thể được tìm thấy ở đây - goo.gl/hnbF5
Adam

@AdamFisher: Bạn có thể vui lòng chia sẻ mã bạn đã sử dụng để tính 10.000 số theo thứ tự không? Tôi thực sự tò mò muốn biết điều đó.
Shumail

4
@AdamFisher Liên kết bạn nhắc đến đã chết.
iRuth

2
Video này sẽ giải thích để hiểu chức năng đệ quy trong 10 phút youtube.com/watch?v=t4MSwiqfLaY
Chathura Palihakkara

2
Ngoài ra còn có một cách tiếp cận lặp đi lặp lại có thể ít khó khăn hơn cho bạn. Bài viết tuyệt vời về cả đệ quy và lặp với mã ở đây - codeflex.co/java-get-fiborie-number-by-index
user5495300

Câu trả lời:


165

Trong chuỗi thứ tự, mỗi mục là tổng của hai phần trước. Vì vậy, bạn đã viết một thuật toán đệ quy.

Vì thế,

fibonacci(5) = fibonacci(4) + fibonacci(3)

fibonacci(3) = fibonacci(2) + fibonacci(1)

fibonacci(4) = fibonacci(3) + fibonacci(2)

fibonacci(2) = fibonacci(1) + fibonacci(0)

Bây giờ bạn đã biết fibonacci(1)==1 and fibonacci(0) == 0. Vì vậy, sau đó bạn có thể tính toán các giá trị khác.

Hiện nay,

fibonacci(2) = 1+0 = 1
fibonacci(3) = 1+1 = 2
fibonacci(4) = 2+1 = 3
fibonacci(5) = 3+2 = 5

Và từ chuỗi Wikipedia 0,1,1,2,3,5,8,13,21....chúng ta có thể thấy rằng đối 5th elementvới chuỗi lượt trả về của Wikipedia 5.

Xem ở đây để xem Hướng dẫn đệ quy .


nó sẽ hoạt động nhưng không được tối ưu hóa cho đến khi và trừ khi được tối ưu hóa. Xin hãy xem câu trả lời của tôi. Hãy cho tôi biết trong trường hợp đề xuất / nhận xét
M Sach

52

Có 2 vấn đề với mã của bạn:

  1. Kết quả được lưu trữ trong int chỉ có thể xử lý 48 số đầu tiên, sau đó, số nguyên điền vào bit và kết quả là sai.
  2. Nhưng bạn không bao giờ có thể chạy MySpace (50).

    fibonacci(n - 1) + fibonacci(n - 2)
    rất sai.
    Vấn đề là nó gọi MySpace không 50 lần mà nhiều hơn thế.
    Đầu tiên, nó gọi Dailymotion (49) + Dailymotion (48),
    tiếp theo (48) + Dailymotion (47) và Dailymotion (47) + Dailymotion (46)
    Mỗi lần nó trở thành Dailymotion (n) tệ hơn, vì vậy độ phức tạp là theo cấp số nhân. nhập mô tả hình ảnh ở đây

Cách tiếp cận mã không đệ quy:

 double fibbonaci(int n){
    double prev=0d, next=1d, result=0d;
    for (int i = 0; i < n; i++) {
        result=prev+next;
        prev=next;
        next=result;
    }
    return result;
}

4
Mặc dù một số câu trả lời khác giải thích đệ quy rõ ràng hơn, đây có lẽ là câu trả lời phù hợp nhất ở mức độ sâu hơn.
Hal50000

1
"Số nguyên điền trừ bit" có nghĩa là gì?
Richard

1
@richard, đó là về cách lưu trữ số nguyên. Sau khi int đạt 2 ^ 31-1, bit tiếp theo là về dấu, do đó số trở nên âm.
chro

Nhanh hơn nhiều sau đó đệ quy. Bảo lưu duy nhất là nó sẽ không hoạt động với n = 1. Cần thêm điều kiện
v0rin

1
"Mỗi lần nó trở nên tệ hơn 2 ^ n" thực sự là tổng số lần gọi hàm 2*fibonacci(n+1)-1, vì vậy nó phát triển với độ phức tạp tương tự như các số của chính nó, là 1.618 ^ n thay vì 2 ^ n
Aemyl

37

Trong mã giả, trong đó n = 5, diễn ra như sau:

Dailymotion (4) + fibonnacci (3)

Điều này được chia thành:

(Dailymotion (3) + fibonnacci (2)) + (Dailymotion (2) + fibonnacci (1))

Điều này được chia thành:

(((Dailymotion (2) + fibonnacci (1)) + ((Dailymotion (1) + fibonnacci (0))) + (((Dailymotion (1) + fibonnacci (0)) + 1))

Điều này được chia thành:

((((Wikipedia (1) + fibonnacci (0)) + 1) + ((1 + 0)) + ((1 + 0) + 1))

Điều này được chia thành:

((((1 + 0) + 1) + ((1 + 0)) + ((1 + 0) + 1))

Kết quả này là: 5

Cho chuỗi sợi quang là 1 1 2 3 5 8 ... , phần tử thứ 5 là 5. Bạn có thể sử dụng cùng một phương pháp để tìm ra các lần lặp khác.


Tôi nghĩ rằng câu trả lời này giải thích các câu hỏi một cách tốt nhất. Thực sự đơn giản
Amit

Đây là gọn gàng. Giải thích cả giá trị ở số thứ n và chuỗi nó theo sau.
Dấu chấm phẩy

12

Đệ quy có thể khó nắm bắt đôi khi. Chỉ cần đánh giá nó trên một tờ giấy cho một số nhỏ:

fib(4)
-> fib(3) + fib(2)
-> fib(2) + fib(1) + fib(1) + fib(0)
-> fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
-> 1 + 0 + 1 + 1 + 0
-> 3

Tôi không chắc chắn cách Java thực sự đánh giá điều này, nhưng kết quả sẽ giống nhau.


trên dòng thứ hai mà 1 và 0 ở cuối đến từ đâu?
pocockn

1
@pocockn fib (2) = fib (1) + fib (0)
tim

Vì vậy, bạn có sợi (4) nên n-1 và n-2 sẽ là sợi (3) + sợi (2) sau đó bạn thực hiện lại n-1 và n-2 bạn nhận được -> sợi (2) + sợi (1) ), bạn đã lấy + xơ (1) + sợi (0) từ đâu? Đã thêm vào cuối
pocockn

@pocockn sợi (2) + sợi (1) là từ sợi (3), sợi (1) + sợi (0) là từ sợi (2)
tim

12

Bạn cũng có thể đơn giản hóa chức năng của mình, như sau:

public int fibonacci(int n)  {
    if (n < 2) return n;

    return fibonacci(n - 1) + fibonacci(n - 2);
}

Làm thế nào là thế này có gì khác biệt so với này hay này hay này câu trả lời?
Tunaki

6
Nó chỉ ngắn hơn và dễ đọc hơn, thuật toán nên luôn luôn là =)
Otavio Ferreira

@OtavioFerreira câu trả lời duy nhất đã giải quyết được vấn đề của tôi, công việc tốt
KKKKK

8
                                F(n)
                                /    \
                            F(n-1)   F(n-2)
                            /   \     /      \
                        F(n-2) F(n-3) F(n-3)  F(n-4)
                       /    \
                     F(n-3) F(n-4)

Điểm quan trọng cần lưu ý là thuật toán này là cấp số nhân vì nó không lưu trữ kết quả của các số được tính toán trước đó. ví dụ F (n-3) được gọi 3 lần.

Để biết thêm chi tiết tham khảo thuật toán của dasgupta chương 0.2


Có một phương pháp lập trình mà chúng ta có thể tránh tính toán F (n) cho cùng một lần nữa bằng cách sử dụng Lập trình động
Amit_Hora

8

Hầu hết các câu trả lời đều hay và giải thích cách thức đệ quy trong MySpace hoạt động.

Dưới đây là một phân tích về ba kỹ thuật bao gồm cả đệ quy:

  1. Đối với vòng lặp
  2. Đệ quy
  3. Ghi nhớ

Đây là mã của tôi để kiểm tra cả ba:

public class Fibonnaci {
    // Output = 0 1 1 2 3 5 8 13

    static int fibMemo[];

    public static void main(String args[]) {
        int num = 20;

        System.out.println("By For Loop");
        Long startTimeForLoop = System.nanoTime();
        // returns the fib series
        int fibSeries[] = fib(num);
        for (int i = 0; i < fibSeries.length; i++) {
            System.out.print(" " + fibSeries[i] + " ");
        }
        Long stopTimeForLoop = System.nanoTime();
        System.out.println("");
        System.out.println("For Loop Time:" + (stopTimeForLoop - startTimeForLoop));


        System.out.println("By Using Recursion");
        Long startTimeRecursion = System.nanoTime();
        // uses recursion
        int fibSeriesRec[] = fibByRec(num);

        for (int i = 0; i < fibSeriesRec.length; i++) {
            System.out.print(" " + fibSeriesRec[i] + " ");
        }
        Long stopTimeRecursion = System.nanoTime();
        System.out.println("");
        System.out.println("Recursion Time:" + (stopTimeRecursion -startTimeRecursion));



        System.out.println("By Using Memoization Technique");
        Long startTimeMemo = System.nanoTime();
        // uses memoization
        fibMemo = new int[num];
        fibByRecMemo(num-1);
        for (int i = 0; i < fibMemo.length; i++) {
            System.out.print(" " + fibMemo[i] + " ");
        }
        Long stopTimeMemo = System.nanoTime();
        System.out.println("");
        System.out.println("Memoization Time:" + (stopTimeMemo - startTimeMemo));

    }


    //fib by memoization

    public static int fibByRecMemo(int num){

        if(num == 0){
            fibMemo[0] = 0;
            return 0;
        }

        if(num ==1 || num ==2){
          fibMemo[num] = 1;
          return 1; 
        }

        if(fibMemo[num] == 0){
            fibMemo[num] = fibByRecMemo(num-1) + fibByRecMemo(num -2);
            return fibMemo[num];
        }else{
            return fibMemo[num];
        }

    }


    public static int[] fibByRec(int num) {
        int fib[] = new int[num];

        for (int i = 0; i < num; i++) {
            fib[i] = fibRec(i);
        }

        return fib;
    }

    public static int fibRec(int num) {
        if (num == 0) {
            return 0;
        } else if (num == 1 || num == 2) {
            return 1;
        } else {
            return fibRec(num - 1) + fibRec(num - 2);
        }
    }

    public static int[] fib(int num) {
        int fibSum[] = new int[num];
        for (int i = 0; i < num; i++) {
            if (i == 0) {
                fibSum[i] = i;
                continue;
            }

            if (i == 1 || i == 2) {
                fibSum[i] = 1;
                continue;
            }

            fibSum[i] = fibSum[i - 1] + fibSum[i - 2];

        }
        return fibSum;
    }

}

Đây là kết quả:

By For Loop
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
For Loop Time:347688
By Using Recursion
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
Recursion Time:767004
By Using Memoization Technique
 0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181 
Memoization Time:327031

Do đó chúng ta có thể thấy ghi nhớ là thời gian tốt nhất và cho vòng lặp phù hợp chặt chẽ.

Nhưng đệ quy mất nhiều thời gian nhất và có thể bạn nên tránh trong cuộc sống thực. Ngoài ra nếu bạn đang sử dụng đệ quy, hãy chắc chắn rằng bạn tối ưu hóa giải pháp.


1
"Ở đây chúng ta có thể thấy vòng lặp là thời gian tốt nhất khôn ngoan"; "Đối với thời gian vòng lặp: 347688"; "Thời gian ghi nhớ: 327031"; 347688> 327031.
AjahnCharles

@CodeConfident Vâng, hôm nay tôi mới thấy lỗi đó và chuẩn bị sửa nó. Dù sao đi nữa cũng xin cám ơn :).
Pritam Banerjee

7

Đây là video tốt nhất mà tôi đã tìm thấy giải thích đầy đủ về đệ quy và chuỗi Fibonacci trong Java.

http://www.youtube.com/watch?v=dsmBRUCzS7k

Đây là mã của anh ấy cho chuỗi và lời giải thích của anh ấy tốt hơn tôi từng cố gắng gõ nó ra.

public static void main(String[] args)
{
    int index = 0;
    while (true)
    {
        System.out.println(fibonacci(index));
        index++;
    }
}
    public static long fibonacci (int i)
    {
        if (i == 0) return 0;
        if (i<= 2) return 1;

        long fibTerm = fibonacci(i - 1) + fibonacci(i - 2);
        return fibTerm;
    }

5

Đối với giải pháp đệ quy của Wikipedia, điều quan trọng là phải lưu đầu ra của các số nhỏ hơn của Wikipedia, trong khi lấy giá trị của số lớn hơn. Điều này được gọi là "Ghi nhớ".

Đây là một mã sử dụng ghi nhớ các giá trị nhỏ hơn của Wikipedia , trong khi lấy số lượng lớn hơn của Wikipedia . Mã này là hiệu quả và không thực hiện nhiều yêu cầu của cùng một chức năng.

import java.util.HashMap;

public class Fibonacci {
  private HashMap<Integer, Integer> map;
  public Fibonacci() {
    map = new HashMap<>();
  }
  public int findFibonacciValue(int number) {
    if (number == 0 || number == 1) {
      return number;
    }
    else if (map.containsKey(number)) {
      return map.get(number);
    }
    else {
      int fibonacciValue = findFibonacciValue(number - 2) + findFibonacciValue(number - 1);
      map.put(number, fibonacciValue);
      return fibonacciValue;
    }
  }
}

4

trong fibonacci chuỗi, hai mặt hàng đầu tiên là 0 và 1, từng hạng mục khác là tổng của hai mục trước. tức là:
0 1 1 2 3 5 8 ...

vì vậy mục thứ 5 là tổng của mục thứ 4 và thứ 3.


4

Michael Goodrich và cộng sự cung cấp một thuật toán thực sự thông minh về Cấu trúc dữ liệu và Thuật toán trong Java, để giải quyết đệ quy đệ quy theo thời gian tuyến tính bằng cách trả về một mảng [fib (n), fib (n-1)].

public static long[] fibGood(int n) {
    if (n < = 1) {
        long[] answer = {n,0};
        return answer;
    } else {
        long[] tmp = fibGood(n-1);
        long[] answer = {tmp[0] + tmp[1], tmp[0]};
        return answer;
    }
}

Điều này mang lại sợi (n) = sợi tốt (n) [0].


4

Đây là giải pháp O (1):

 private static long fibonacci(int n) {
    double pha = pow(1 + sqrt(5), n);
    double phb = pow(1 - sqrt(5), n);
    double div = pow(2, n) * sqrt(5);

    return (long) ((pha - phb) / div);
}

Công thức số Fibonacci của Binet được sử dụng để thực hiện ở trên. Đối với đầu vào lớn longcó thể được thay thế bằng BigDecimal.


3

Một chuỗi Fftimeacci là một chuỗi tính tổng kết quả của một số khi được thêm vào kết quả trước đó bắt đầu bằng 1.

      so.. 1 + 1 = 2
           2 + 3 = 5
           3 + 5 = 8
           5 + 8 = 13
           8 + 13 = 21

Một khi chúng ta hiểu Fftimeacci là gì, chúng ta có thể bắt đầu phá mã.

public int fibonacci(int n)  {
    if(n == 0)
        return 0;
    else if(n == 1)
      return 1;
   else
      return fibonacci(n - 1) + fibonacci(n - 2);
}

Đầu tiên nếu statment kiểm tra một trường hợp cơ sở, trong đó vòng lặp có thể thoát ra. Mặt khác nếu câu lệnh bên dưới đang làm như vậy, nhưng nó có thể được viết lại như vậy ...

    public int fibonacci(int n)  {
        if(n < 2)
             return n;

        return fibonacci(n - 1) + fibonacci(n - 2);
    }

Bây giờ, khi một trường hợp cơ sở được thiết lập, chúng ta phải hiểu ngăn xếp cuộc gọi. Cuộc gọi đầu tiên của bạn đến "Dailymotion" sẽ là lần cuối cùng giải quyết trên ngăn xếp (chuỗi cuộc gọi) khi chúng giải quyết theo thứ tự ngược mà chúng được gọi. Phương thức cuối cùng được gọi là giải quyết trước, sau đó là phương thức cuối cùng được gọi trước phương thức đó và cứ thế ...

Vì vậy, tất cả các cuộc gọi được thực hiện trước khi mọi thứ được "tính toán" với các kết quả đó. Với đầu vào là 8, chúng tôi dự kiến ​​đầu ra là 21 (xem bảng trên).

Dailymotion (n - 1) tiếp tục được gọi cho đến khi nó đạt đến trường hợp cơ sở, sau đó, Wikipedia (n - 2) được gọi cho đến khi nó đạt đến trường hợp cơ sở. Khi ngăn xếp bắt đầu tính tổng kết quả theo thứ tự ngược lại, kết quả sẽ như vậy ...

1 + 1 = 1        ---- last call of the stack (hits a base case).
2 + 1 = 3        ---- Next level of the stack (resolving backwards).
2 + 3 = 5        ---- Next level of the stack (continuing to resolve).

Họ tiếp tục sủi bọt (giải quyết ngược) cho đến khi tổng chính xác được trả về cuộc gọi đầu tiên trong ngăn xếp và đó là cách bạn nhận được câu trả lời của mình.

Phải nói rằng, thuật toán này rất kém hiệu quả vì nó tính toán kết quả tương tự cho mỗi nhánh mà mã được chia thành. Một cách tiếp cận tốt hơn nhiều là một cách "từ dưới lên" trong đó không yêu cầu Ghi nhớ (bộ nhớ đệm) hoặc đệ quy (ngăn xếp cuộc gọi sâu).

Giống như vậy ...

        static int BottomUpFib(int current)
        {
            if (current < 2) return current;

            int fib = 1;
            int last = 1;

            for (int i = 2; i < current; i++)
            {
                int temp = fib;
                fib += last;
                last = temp;
            }

            return fib;
        }

2

Hầu hết các giải pháp được cung cấp ở đây chạy trong độ phức tạp O (2 ^ n). Tính toán lại các nút giống hệt nhau trong cây đệ quy là không hiệu quả và lãng phí chu kỳ CPU.

Chúng ta có thể sử dụng ghi nhớ để làm cho chức năng MySpace chạy trong thời gian O (n)

public static int fibonacci(int n) {
    return fibonacci(n, new int[n + 1]);
}

public static int fibonacci(int i, int[] memo) {

    if (i == 0 || i == 1) {
        return i;
    }

    if (memo[i] == 0) {
        memo[i] = fibonacci(i - 1, memo) + fibonacci(i - 2, memo);
    }
    return memo[i];
}

Nếu chúng ta theo lộ trình lập trình động từ dưới lên, mã bên dưới đủ đơn giản để tính toán Wikipedia:

public static int fibonacci1(int n) {
    if (n == 0) {
        return n;
    } else if (n == 1) {
        return n;
    }
    final int[] memo = new int[n];

    memo[0] = 0;
    memo[1] = 1;

    for (int i = 2; i < n; i++) {
        memo[i] = memo[i - 1] + memo[i - 2];
    }
    return memo[n - 1] + memo[n - 2];
}

2

Tại sao câu trả lời này là khác nhau

Mọi câu trả lời khác:

  • In thay vì trả về
  • Thực hiện 2 cuộc gọi đệ quy mỗi lần lặp
  • Bỏ qua câu hỏi bằng cách sử dụng các vòng lặp

(sang một bên: không có cách nào trong số này thực sự hiệu quả; hãy sử dụng công thức của Binet để tính trực tiếp thuật ngữ thứ n )

Đuôi đệ quy

Đây là một cách tiếp cận đệ quy để tránh một cuộc gọi đệ quy kép bằng cách chuyển cả câu trả lời trước VÀ câu trả lời trước đó.

private static final int FIB_0 = 0;
private static final int FIB_1 = 1;

private int calcFibonacci(final int target) {
    if (target == 0) { return FIB_0; }
    if (target == 1) { return FIB_1; }

    return calcFibonacci(target, 1, FIB_1, FIB_0);
}

private int calcFibonacci(final int target, final int previous, final int fibPrevious, final int fibPreviousMinusOne) {
    final int current = previous + 1;
    final int fibCurrent = fibPrevious + fibPreviousMinusOne;
    // If you want, print here / memoize for future calls

    if (target == current) { return fibCurrent; }

    return calcFibonacci(target, current, fibCurrent, fibPrevious);
}

1

Đây là một chuỗi cơ bản hiển thị hoặc nhận đầu ra 1 1 2 3 5 8 nó là một chuỗi mà tổng của số trước đó số hiện tại sẽ được hiển thị tiếp theo.

Hãy thử xem liên kết bên dưới Hướng dẫn trình tự Fibros đệ quy Java

public static long getFibonacci(int number){
if(number<=1) return number;
else return getFibonacci(number-1) + getFibonacci(number-2);
}

Bấm vào đây Xem Hướng dẫn trình tự Fibros đệ quy Java để cho ăn bằng thìa


Những gì anh ta cần phải hiểu là cách mã hoạt động và tại sao nó được viết theo cách chúng được viết.
Adarsh

Tôi nghĩ rằng tôi đề cập đến trong câu đầu tiên của tôi làm thế nào nó hoạt động? tôi viết mã để làm cho nó đơn giản hơn. btw, xin lỗi.
Jaymelson Galang

Không có gì sai với mã của bạn. Chỉ có anh chàng muốn hiểu làm thế nào mã đó làm việc. Kiểm tra câu trả lời của RanRag. Một cái gì đó thuộc loại đó :)
Adarsh

ahh ok, xin lỗi tôi là người mới bắt đầu ở đây trong stackoverflow. chỉ muốn giúp ^ _ ^
Jaymelson Galang

1

Tôi nghĩ rằng đây là một cách đơn giản:

public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int number = input.nextInt();
        long a = 0;
        long b = 1;
        for(int i = 1; i<number;i++){
            long c = a +b;
            a=b;
            b=c;
            System.out.println(c);
        }
    }
}

1

Câu trả lời của RanRag (được chấp nhận) sẽ hoạt động tốt nhưng đó không phải là giải pháp tối ưu cho đến khi và trừ khi nó được ghi nhớ như được giải thích trong câu trả lời của Anil.

Đối với xem xét đệ quy dưới đây, các cuộc gọi phương thức TestFibonaccilà tối thiểu

public class TestFibonacci {

    public static void main(String[] args) {

        int n = 10;

        if (n == 1) {
            System.out.println(1);

        } else if (n == 2) {
            System.out.println(1);
            System.out.println(1);
        } else {
            System.out.println(1);
            System.out.println(1);
            int currentNo = 3;
            calFibRec(n, 1, 1, currentNo);
        }

    }

    public static void calFibRec(int n, int secondLast, int last,
            int currentNo) {
        if (currentNo <= n) {

            int sum = secondLast + last;
            System.out.println(sum);
            calFibRec(n, last, sum, ++currentNo);
        }
    }

}

1
public class febo 
{
 public static void main(String...a)
 {
  int x[]=new int[15];  
   x[0]=0;
   x[1]=1;
   for(int i=2;i<x.length;i++)
   {
      x[i]=x[i-1]+x[i-2];
   }
   for(int i=0;i<x.length;i++)
   {
      System.out.println(x[i]);
   }
 }
}

1

Bằng cách sử dụng một concienHashMap nội bộ về mặt lý thuyết có thể cho phép triển khai đệ quy này hoạt động đúng trong môi trường đa luồng, tôi đã triển khai một hàm sợi sử dụng cả BigInteger và Recursion. Mất khoảng 53ms để tính 100 số sợi đầu tiên.

private final Map<BigInteger,BigInteger> cacheBig  
    = new ConcurrentHashMap<>();
public BigInteger fibRecursiveBigCache(BigInteger n) {
    BigInteger a = cacheBig.computeIfAbsent(n, this::fibBigCache);
    return a;
}
public BigInteger fibBigCache(BigInteger n) {
    if ( n.compareTo(BigInteger.ONE ) <= 0 ){
        return n;
    } else if (cacheBig.containsKey(n)){
        return cacheBig.get(n);
    } else {
        return      
            fibBigCache(n.subtract(BigInteger.ONE))
            .add(fibBigCache(n.subtract(TWO)));
    }
}

Mã kiểm tra là:

@Test
public void testFibRecursiveBigIntegerCache() {
    long start = System.currentTimeMillis();
    FibonacciSeries fib = new FibonacciSeries();
    IntStream.rangeClosed(0,100).forEach(p -&R {
        BigInteger n = BigInteger.valueOf(p);
        n = fib.fibRecursiveBigCache(n);
        System.out.println(String.format("fib of %d is %d", p,n));
    });
    long end = System.currentTimeMillis();
    System.out.println("elapsed:" + 
    (end - start) + "," + 
    ((end - start)/1000));
}
và đầu ra từ thử nghiệm là:
    .
    .
    .
    .
    .
    sợi của 93 là 12200160415121876738
    sợi 94 là 19740274219868223167
    số sợi 95 là 31940434634990099905
    số xơ 96 là 51680708854858323072
    số sợi 97 là 83621143489848422977
    sợi của 98 là 135301852344706746049
    sợi 99 là 218922995834555169026
    số xơ là 1004224848179261915075
    trôi qua: 58,0

1

Dưới đây là một đệ quy febonacci một dòng:

public long fib( long n ) {
        return n <= 0 ? 0 : n == 1 ? 1 : fib( n - 1 ) + fib( n - 2 );
}

1

Thử cái này

private static int fibonacci(int n){
    if(n <= 1)
        return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

0

Chỉ để bổ sung, nếu bạn muốn có thể tính toán số lượng lớn hơn, bạn nên sử dụng BigInteger.

Một ví dụ lặp đi lặp lại.

import java.math.BigInteger;
class Fibonacci{
    public static void main(String args[]){
        int n=10000;
        BigInteger[] vec = new BigInteger[n];
        vec[0]=BigInteger.ZERO;
        vec[1]=BigInteger.ONE;
        // calculating
        for(int i = 2 ; i<n ; i++){
            vec[i]=vec[i-1].add(vec[i-2]);
        }
        // printing
        for(int i = vec.length-1 ; i>=0 ; i--){
            System.out.println(vec[i]);
            System.out.println("");
        }
    }
}

0

http://en.wikipedia.org/wiki/Fiborie_number để biết thêm chi tiết

public class Fibonacci {

    public static long fib(int n) {
        if (n <= 1) return n;
        else return fib(n-1) + fib(n-2);
    }

    public static void main(String[] args) {
        int N = Integer.parseInt(args[0]);
        for (int i = 1; i <= N; i++)
            System.out.println(i + ": " + fib(i));
    }

}

Làm cho nó đơn giản như cần thiết không cần sử dụng vòng lặp while và vòng lặp khác


0
public class FibonacciSeries {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        for (int i = 0; i <= N; i++) {
            int result = fibonacciSeries(i);
            System.out.println(result);
        }
        scanner.close();
    }

    private static int fibonacciSeries(int n) {
        if (n < 0) {
            return 1;
        } else if (n > 0) {
            return fibonacciSeries(n - 1) + fibonacciSeries(n - 2);
        }
        return 0;
    }
}

0

Sử dụng while:

public int fib(int index) {
    int tmp = 0, step1 = 0, step2 = 1, fibNumber = 0;
    while (tmp < index - 1) {
        fibNumber = step1 + step2;
        step1 = step2;
        step2 = fibNumber;
        tmp += 1;
    };
    return fibNumber;
}

Ưu điểm của giải pháp này là dễ đọc mã và hiểu mã, hy vọng nó có ích


0

Một chuỗi Fftimeacci là một chuỗi tổng hợp kết quả của một số sau đó chúng tôi đã thêm vào kết quả trước đó, chúng tôi nên bắt đầu từ 1. Tôi đã cố gắng tìm một giải pháp dựa trên thuật toán, vì vậy tôi xây dựng mã đệ quy, nhận thấy rằng tôi giữ số trước và tôi đã thay đổi vị trí. Tôi đang tìm kiếm trình tự Fftimeacci từ 1 đến 15.

public static void main(String args[]) {

    numbers(1,1,15);
}


public static int numbers(int a, int temp, int target)
{
    if(target <= a)
    {
        return a;
    }

    System.out.print(a + " ");

    a = temp + a;

    return numbers(temp,a,target);
}

-1
 public static long fib(int n) {
    long population = 0;

    if ((n == 0) || (n == 1)) // base cases
    {
        return n;
    } else // recursion step
    {

        population+=fib(n - 1) + fib(n - 2);
    }

    return population;
}

-1

Fibros đơn giản

public static void main(String[]args){

    int i = 0;
    int u = 1;

    while(i<100){
        System.out.println(i);
        i = u+i;
        System.out.println(u);
        u = u+i;
    }
  }
}

2
Chào mừng đến với SO. Trong khi câu trả lời của bạn không tính được chuỗi Fibonacci. Câu trả lời của bạn không trả lời OP, người đã hỏi về các hàm đệ quy.
James K

-2

@chro là tại chỗ, nhưng anh ấy không chỉ ra cách chính xác để làm điều này một cách đệ quy. Đây là giải pháp:

class Fib {
    static int count;

    public static void main(String[] args) {
        log(fibWrong(20));  // 6765
        log("Count: " + count); // 21891
        count = 0;
        log(fibRight(20)); // 6765
        log("Count: " + count); // 19
    }

    static long fibRight(long n) {
        return calcFib(n-2, 1, 1);
    }

    static long fibWrong(long n) {
        count++;
        if (n == 0 || n == 1) {
            return n;
        } else if (n < 0) {
            log("Overflow!");
            System.exit(1);
            return n;
        } else {
            return fibWrong(n-1) + fibWrong(n-2);
        }

    }

    static long calcFib(long nth, long prev, long next) {
        count++;
        if (nth-- == 0)
            return next;
        if (prev+next < 0) {
            log("Overflow with " + (nth+1) 
                + " combinations remaining");
            System.exit(1);
        }
        return calcFib(nth, next, prev+next);
    }

    static void log(Object o) {
        System.out.println(o);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.