Java ลำดับ Fibonacci แบบเรียกซ้ำ


156

โปรดอธิบายรหัสง่าย ๆ นี้:

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

ฉันสับสนกับบรรทัดสุดท้ายโดยเฉพาะอย่างยิ่งเพราะถ้าเช่น n = 5 แล้ว fibonacci (4) + fibonacci (3) จะถูกเรียกและต่อไป แต่ฉันไม่เข้าใจว่าอัลกอริทึมนี้คำนวณค่าที่ดัชนี 5 โดยวิธีนี้ได้อย่างไร วิธี. โปรดอธิบายด้วยรายละเอียดมากมาย!


8
โปรดทราบว่านี่เป็นการเรียกซ้ำและทำงานในเวลาเอ็กซ์โปเนนเชียล มันไม่มีประสิทธิภาพสำหรับค่าขนาดใหญ่ของ N โดยใช้วิธีการวนซ้ำฉันสามารถคำนวณ 10,000 ตัวเลขแรกในลำดับ พวกเขาสามารถพบได้ที่นี่ - goo.gl/hnbF5
อดัม

@ AdamFisher: คุณช่วยแบ่งปันรหัสที่คุณใช้ในการคำนวณ 10,000 ตัวเลขตามลำดับได้ไหม? ฉันอยากรู้จริงๆ
Shumail

4
@ AdamFisher ลิงก์ที่คุณอ้างถึงนั้นตายแล้ว
iRuth

2
วิดีโอนี้จะอธิบายให้เข้าใจถึงฟังก์ชั่นวนซ้ำใน 10 นาทีyoutube.com/watch?v=t4MSwiqfLaY
Chathura Palihakkara

2
นอกจากนี้ยังมีวิธีการวนซ้ำซึ่งอาจเป็นเรื่องยากสำหรับคุณ บทความยอดเยี่ยมเกี่ยวกับทั้งวนซ้ำและซ้ำด้วยรหัสที่นี่ - codeflex.co/java-get-fibonacci-number-by-index
user5495300

คำตอบ:


165

ในลำดับฟีโบนักชีแต่ละไอเท็มคือผลรวมของสองอันก่อนหน้า ดังนั้นคุณเขียนอัลกอริทึมแบบเรียกซ้ำ

ดังนั้น,

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

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

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

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

fibonacci(1)==1 and fibonacci(0) == 0ตอนนี้คุณรู้อยู่แล้วว่า ดังนั้นคุณสามารถคำนวณค่าอื่น ๆ ได้ในภายหลัง

ตอนนี้

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

และจากลำดับฟีโบนักชี0,1,1,2,3,5,8,13,21....เราจะเห็นได้ว่าสำหรับ5th elementลำดับฟีโบนักชีกลับ5มา

ดูที่นี่สำหรับRecursion กวดวิชา


มันจะทำงานได้ แต่ไม่ได้รับการปรับให้ดีที่สุดจนกระทั่ง โปรดดูคำตอบของฉัน แจ้งให้เราทราบในกรณีที่มีข้อเสนอแนะ / ความคิดเห็น
M Sach

52

รหัสของคุณมี 2 ปัญหา:

  1. ผลลัพธ์ถูกเก็บใน int ซึ่งสามารถจัดการได้เพียง 48 หมายเลขแรกของฟีโบนักชีหลังจากนี้จำนวนเต็มเติมลบด้วยบิตและผลลัพธ์ไม่ถูกต้อง
  2. แต่คุณไม่สามารถเรียกใช้ฟีโบนักชี (50)
    รหัส
    fibonacci(n - 1) + fibonacci(n - 2)
    ผิดมาก
    ปัญหาคือว่ามันเรียกว่าฟีโบนักชีไม่ได้ 50 ครั้ง แต่มีอีกมาก
    ตอนแรกเรียกว่าฟีโบนักชี (49) + ฟีโบนักชี (48)
    ฟีโบนักชีต่อไป (48) + ฟีโบนักชี (47) และฟีโบนักชี (47) + ฟีโบนักชี (46)
    ทุกครั้งที่ฟีโบนัชชี ป้อนคำอธิบายรูปภาพที่นี่

วิธีการของโค้ดที่ไม่เรียกซ้ำ:

 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
แม้ว่าคำตอบอื่น ๆ บางคำอธิบายการเรียกซ้ำอย่างชัดเจนยิ่งขึ้นนี่อาจเป็นคำตอบที่เกี่ยวข้องที่สุดในระดับที่ลึกกว่า
Hal50000

1
"จำนวนเต็มเติมเต็มลบบิต" หมายความว่าอะไร
richard

1
@ Richard มันเป็นเรื่องเกี่ยวกับวิธีการเก็บจำนวนเต็ม หลังจากถึง int 2 ^ 31-1 บิตถัดไปเป็นเรื่องเกี่ยวกับสัญญาณดังนั้นจำนวนกลายเป็นลบ
chro

เร็วขึ้นมากซ้ำแล้วซ้ำอีก การจองเพียงอย่างเดียวคือมันจะไม่ทำงานสำหรับ n = 1 จำเป็นต้องมีเงื่อนไขเพิ่มเติม
v0rin

1
"ทุกครั้งที่มันแย่ลง 2 ^ n"จริง ๆ แล้วจำนวนการเรียกใช้ฟังก์ชันทั้งหมด2*fibonacci(n+1)-1จึงเพิ่มขึ้นด้วยความซับซ้อนเช่นเดียวกับหมายเลข
ฟีโบนักชี

37

ในโค้ดหลอกที่ n = 5 จะเกิดขึ้นต่อไปนี้:

fibonacci (4) + fibonnacci (3)

สิ่งนี้แบ่งออกเป็น:

(fibonacci (3) + fibonnacci (2)) + (fibonacci (2) + fibonnacci (1)

สิ่งนี้แบ่งออกเป็น:

(((fibonacci (2) + fibonnacci (1)) + ((fibonacci (1) + fibonnacci (0))) + ((fibonacci (1) + fibonnacci (0)) + 1))

สิ่งนี้แบ่งออกเป็น:

((((fibonacci (1) + fibonnacci (0)) + 1) + ((1 + 0)) + ((1 + 0) + 1))

สิ่งนี้แบ่งออกเป็น:

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

ผลลัพธ์นี้ใน: 5

เมื่อพิจารณาลำดับของฟีโบนัชชีคือ1 1 2 3 5 8 ...องค์ประกอบที่ 5 คือ 5 คุณสามารถใช้วิธีการเดียวกันในการคำนวณการทำซ้ำอื่น ๆ


ฉันคิดว่าคำตอบนี้อธิบายคำถามด้วยวิธีที่ดีที่สุด ง่ายจริงๆ
Amit

นี่มันเรียบร้อย อธิบายทั้งค่าในระยะที่ n และชุดข้อมูลที่ตามมา
Semicolon

12

การเรียกซ้ำอาจเป็นเรื่องยากที่จะเข้าใจในบางครั้ง เพียงประเมินบนกระดาษสำหรับจำนวนน้อย:

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

ฉันไม่แน่ใจว่า Java ประเมินผลจริงอย่างไร แต่ผลลัพธ์จะเหมือนกัน


บนบรรทัดที่สองที่ 1 และ 0 ในตอนท้ายมาจากไหน?
pocockn

1
@pocockn Fib (2) = fib (1) + fib (0)
ทิม

ดังนั้นคุณมีปี่ (4) ดังนั้น n-1 และ n-2 จะเป็นตอแหล (3) + ตอแหล (2) จากนั้นคุณทำ n-1 และ n-2 อีกครั้งที่คุณได้รับ -> ตอแหล (2) + ตอแหล (1) ) คุณได้รับ + ​​fib (1) + fib (0) จากที่ไหน เพิ่มไปยังจุดสิ้นสุด
pocockn

@pockock fib (2) + fib (1) มาจาก fib (3), fib (1) + fib (0) มาจาก fib (2)
Tim

12

คุณยังสามารถทำให้ฟังก์ชันของคุณง่ายขึ้นดังนี้:

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

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

วิธีนี้จะแตกต่างใด ๆ กว่านี้หรือนี้หรือนี้คำตอบ?
Tunaki

6
มันสั้นและง่ายต่อการอ่านซึ่งอัลกอริธึมควรเป็น =)
Otavio Ferreira

@OtavioFerreira คำตอบเดียวที่จัดการเพื่อแก้ปัญหาของฉันได้เป็นอย่างดี
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)

จุดสำคัญที่ควรทราบคืออัลกอริธึมนี้เป็นเลขยกกำลังเนื่องจากมันไม่ได้เก็บผลลัพธ์ของตัวเลขที่คำนวณไว้ก่อนหน้านี้ เช่น F (n-3) เรียกว่า 3 ครั้ง

สำหรับรายละเอียดเพิ่มเติมดูอัลกอริทึมโดย dasgupta บทที่ 0.2


มีวิธีการเขียนโปรแกรมซึ่งเราสามารถหลีกเลี่ยงการคำนวณ F (n) สำหรับ n เดียวกันซ้ำแล้วซ้ำอีกโดยใช้ Dynamic Programming
Amit_Hora

8

คำตอบส่วนใหญ่นั้นดีและอธิบายว่าการวนเวียนใน Fibonacci ซ้ำได้อย่างไร

นี่คือการวิเคราะห์เกี่ยวกับสามเทคนิคซึ่งรวมถึงการเรียกซ้ำด้วย:

  1. สำหรับวน
  2. recursion
  3. memoization

นี่คือรหัสของฉันเพื่อทดสอบทั้งสาม:

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;
    }

}

นี่คือผลลัพธ์:

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

ดังนั้นเราสามารถเห็นบันทึกช่วยจำเป็นเวลาที่ดีที่สุดที่ชาญฉลาดและสำหรับการแข่งขันวนรอบอย่างใกล้ชิด

แต่การเรียกซ้ำใช้เวลานานที่สุดและอาจเป็นคุณควรหลีกเลี่ยงในชีวิตจริง นอกจากนี้หากคุณใช้การเรียกซ้ำตรวจสอบให้แน่ใจว่าคุณเพิ่มประสิทธิภาพการแก้ปัญหา


1
"ที่นี่เราจะเห็นว่าการวนซ้ำเป็นเวลาที่ดีที่สุด"; "สำหรับช่วงเวลาวนซ้ำ: 347688"; "เวลาการจำ: 327031"; 347688> 327031.
AjahnCharles

@ CodeConfident ใช่ฉันเพิ่งเห็นความผิดพลาดนั้นวันนี้และกำลังจะแก้ไข ขอบคุณ anyways :)
Pritam Banerjee

7

นี่คือวิดีโอที่ดีที่สุดที่ฉันพบว่าอธิบายการเรียกซ้ำและลำดับ Fibonacci ใน Java อย่างสมบูรณ์

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

นี่คือรหัสของเขาสำหรับลำดับและคำอธิบายของเขาดีกว่าที่ฉันเคยลองพิมพ์ออกมา

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

สำหรับฟีโบนักชีแบบวนซ้ำมันเป็นสิ่งสำคัญที่จะต้องบันทึกเอาท์พุทของตัวเลขฟีโบนักชีที่มีขนาดเล็กลงในขณะที่รับค่าจำนวนที่มากขึ้น สิ่งนี้เรียกว่า "การบันทึก"

นี่คือรหัสที่ใช้ในการบันทึกค่าฟีโบนักชีที่มีขนาดเล็กลงในขณะที่ดึงข้อมูลฟีโบนักชีขนาดใหญ่ขึ้น รหัสนี้มีประสิทธิภาพและไม่ทำการร้องขอหลายฟังก์ชั่นเดียวกัน

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

ในfibonacciลำดับสองรายการแรกเป็น 0 และ 1 แต่ละรายการอื่น ๆ ที่เป็นผลรวมของสองรายการก่อนหน้านี้ ie:
0 1 1 2 3 5 8 ...

ดังนั้นรายการที่ 5 คือผลรวมของรายการที่ 4 และ 3


4

Michael Goodrich และคณะได้จัดทำอัลกอริทึมที่ชาญฉลาดในโครงสร้างข้อมูลและอัลกอริทึมใน Java เพื่อแก้ปัญหาฟีโบนักชีในเวลาเชิงเส้นโดยส่งกลับอาร์เรย์ของ [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;
    }
}

สิ่งนี้ทำให้ได้ Fib (n) = fibGood (n) [0]


4

นี่คือโซลูชัน 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);
}

สูตรหมายเลขฟีโบนัชชีของ Binetใช้สำหรับการนำไปใช้งานด้านบน สำหรับปัจจัยการผลิตที่มีขนาดใหญ่สามารถถูกแทนที่ด้วยlongBigDecimal


3

ลำดับ Fibbonacci คือลำดับที่รวมผลลัพธ์ของตัวเลขเมื่อบวกกับผลลัพธ์ก่อนหน้าโดยเริ่มต้นด้วย 1

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

เมื่อเราเข้าใจว่า Fibbonacci คืออะไรเราสามารถเริ่มทำลายรหัสได้

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

ครั้งแรกถ้า statment ตรวจสอบกรณีฐานที่วงสามารถแบ่งออก คำสั่งอื่นด้านล่างถ้าทำเช่นเดียวกัน แต่สามารถเขียนซ้ำได้เช่นนั้น ...

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

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

ตอนนี้กรณีพื้นฐานคือการสร้างเราต้องเข้าใจ call stack การโทรครั้งแรกของคุณไปที่ "fibonacci" จะเป็นครั้งสุดท้ายที่จะแก้ไขใน stack (ลำดับการโทร) ตามที่พวกเขาแก้ไขในลำดับย้อนกลับที่พวกเขาถูกเรียก วิธีสุดท้ายที่เรียกว่าแก้ไขก่อนแล้วจึงถูกเรียกก่อนหน้านั้นก่อนและต่อ ...

ดังนั้นการโทรทั้งหมดจะถูกทำก่อนสิ่งใด ๆ ที่ "คำนวณ" กับผลลัพธ์เหล่านั้น ด้วยอินพุต 8 เราคาดหวังผลลัพธ์ที่ 21 (ดูตารางด้านบน)

ฟีโบนักชี (n - 1) ยังคงถูกเรียกจนกว่าจะถึงเคสฐานจากนั้นฟีโบนักชี (n - 2) จะถูกเรียกจนกว่าจะถึงเคสพื้นฐาน เมื่อสแต็คเริ่มรวมผลลัพธ์ในลำดับย้อนกลับผลลัพธ์จะเป็นเช่นนั้น ...

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).

พวกเขายังคงเดือดปุด ๆ (แก้ไขไปข้างหลัง) จนถึงผลรวมที่ถูกต้องจะถูกส่งกลับไปที่สายแรกในสแต็คและนั่นคือวิธีที่คุณได้รับคำตอบ

ต้องบอกว่าอัลกอริทึมนี้ไม่มีประสิทธิภาพมากเพราะจะคำนวณผลลัพธ์เดียวกันสำหรับแต่ละสาขาที่รหัสแยกออกเป็น วิธีที่ดีกว่าคือ "ด้านล่าง" ที่ไม่ต้องมีการบันทึก (แคช) หรือการเรียกซ้ำ (call call stack) ที่ลึก

ชอบมาก ...

        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

โซลูชันส่วนใหญ่ที่นำเสนอที่นี่ทำงานในความซับซ้อน O (2 ^ n) การคำนวณโหนดที่เหมือนกันในทรีแบบเรียกซ้ำไม่มีประสิทธิภาพและทำให้สิ้นเปลืองวงจร CPU

เราสามารถใช้บันทึกช่วยจำเพื่อให้ฟังก์ชัน fibonacci ทำงานในเวลา 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];
}

หากเราติดตามเส้นทางการเขียนโปรแกรมแบบไดนามิก Bottom-Up รหัสด้านล่างนั้นง่ายพอที่จะคำนวณ fibonacci:

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

ทำไมคำตอบนี้จึงแตกต่าง

ทุกคำตอบอื่น ๆ :

  • พิมพ์แทนการส่งคืน
  • ทำให้การโทรซ้ำ 2 ครั้งต่อการวนซ้ำ
  • ไม่สนใจคำถามโดยใช้ลูป

(นอกเหนือ: ไม่มีของเหล่านี้มีประสิทธิภาพจริงการใช้สูตรของ Binetโดยตรงคำนวณ n THระยะ)

หาง Recursive Fib

นี่คือวิธีเรียกซ้ำที่หลีกเลี่ยงการโทรซ้ำโดยการส่งคำตอบก่อนหน้านี้และคำตอบก่อนหน้านั้น

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

มันเป็นลำดับขั้นพื้นฐานที่แสดงหรือรับเอาท์พุท 1 1 2 3 5 8 มันเป็นลำดับที่ผลรวมของจำนวนก่อนหน้านี้จำนวนปัจจุบันจะแสดงต่อไป

ลองดูลิงค์ข้างล่างนี้ Java Recursive Fibonacci Sequence Tutorial

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

คลิกที่นี่ดูการสอนลำดับ Fibonacci แบบเรียกซ้ำ Javaสำหรับการป้อนช้อน


สิ่งที่เขาต้องการที่จะเข้าใจได้ว่ารหัสการทำงานและทำไมมันเป็นวิธีที่พวกเขาเขียนมันถูกเขียน
Adarsh

ฉันคิดว่าฉันพูดถึงในประโยคแรกของฉันมันทำงานอย่างไร ฉันเขียนรหัสเพื่อทำให้ง่ายขึ้น BTW ขอโทษ
Jaymelson Galang

ไม่มีอะไรผิดปกติกับรหัสของคุณ มีเพียงผู้ชายเท่านั้นที่ต้องการเข้าใจวิธีการทำงานของรหัส ตรวจสอบคำตอบโดย RanRag บางสิ่งบางอย่างของการจัดเรียงที่ :)
Adarsh

อ่าขอโทษด้วยฉันเป็นผู้เริ่มต้นที่นี่ใน stackoverflow เพียงแค่ต้องการความช่วยเหลือ ^ _ ^
Jaymelson Galang

1

ฉันคิดว่านี่เป็นวิธีที่ง่าย:

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

RanRag (ยอมรับ) คำตอบที่จะทำงานได้ดี แต่ที่ไม่เหมาะสมการแก้ปัญหาจนและถ้ามันจะจำตามที่อธิบายไว้ในคำตอบคราม

สำหรับการพิจารณาแบบเรียกซ้ำด้านล่างวิธีการเรียกใช้ของTestFibonacciขั้นต่ำ

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

ด้วยการใช้ ConcurrentHashMap ภายในซึ่งในทางทฤษฎีอาจอนุญาตให้การใช้งานแบบเรียกซ้ำนี้ทำงานอย่างถูกต้องในสภาพแวดล้อมแบบมัลติเธรดฉันได้ใช้ฟังก์ชั่นตอแหลที่ใช้ทั้ง BigInteger และ Recursion ใช้เวลาประมาณ 53 มิลลิวินาทีในการคำนวณตัวเลข 100 อันดับแรก

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)));
    }
}

รหัสการทดสอบคือ:

@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));
}
และผลลัพธ์จากการทดสอบคือ:
    .
    .
    .
    .
    .
    ตอแหล 93 เป็น 12200160415121876738
    ตอแหลของ 94 คือ 19740274219868223167
    ตอแหลของ 95 คือ 31940434634990099905
    ตอแหลของ 96 คือ 51680708854858323072
    fib ของ 97 คือ 83621143489848422977
    Fib ของ 98 คือ 135301852344706746049
    Fib ของ 99 คือ 218922995834555169026
    Fib ของ 100 คือ 354224848179261915075
    ผ่านไป: 58,0

1

นี่คือหนึ่งบรรทัด febonacci recursive:

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


0

เพียงเพื่อเสริมถ้าคุณต้องการที่จะคำนวณตัวเลขที่ใหญ่กว่าคุณควรใช้ BigInteger

ตัวอย่างซ้ำ

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/Fibonacci_numberรายละเอียดเพิ่มเติม

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));
    }

}

ทำให้มันง่ายอย่างที่ต้องการไม่จำเป็นต้องใช้ในขณะที่วงและวงอื่น ๆ


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

การใช้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;
}

ข้อดีของการแก้ปัญหานี้คือมันง่ายต่อการอ่านรหัสและเข้าใจมันหวังว่ามันจะช่วย


0

ลำดับ Fibbonacci คือตัวเลขที่รวมผลลัพธ์ของตัวเลขจากนั้นเราได้เพิ่มเข้าไปในผลลัพธ์ก่อนหน้าเราควรเริ่มจาก 1 ฉันพยายามหาวิธีแก้ปัญหาตามอัลกอริทึมดังนั้นฉันจึงสร้างรหัสซ้ำ หมายเลขก่อนหน้าและฉันเปลี่ยนตำแหน่ง ฉันกำลังค้นหาลำดับ Fibbonacci จาก 1 ถึง 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

Fibonacci ง่าย

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
ยินดีต้อนรับสู่ SO ในขณะที่คำตอบของคุณคำนวณลำดับฟีโบนักชี คำตอบของคุณไม่ตอบ OP ผู้ที่ถามเกี่ยวกับฟังก์ชันแบบเรียกซ้ำ
James K

-2

@chro เป็นจุดบน แต่ s / เขาไม่แสดงวิธีที่ถูกต้องในการทำซ้ำนี้ นี่คือทางออก:

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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.