swift 斐波那契数列

67 阅读1分钟

首先提供个检查耗时方法

import Foundation

struct TimeTool {
    static func checkFuncTime(file: NSString = #file, task: () -> Void) {
        print("----------【file: \(file.lastPathComponent) func: checkFuncTime START】----------")
        let startTime = Int(Date().timeIntervalSince1970)
        task()
        let endTime = Int(Date().timeIntervalSince1970)
        print("----------【file: \(file.lastPathComponent) func: checkFuncTime 耗时 \(endTime - startTime)秒】----------")
        print("----------【file: \(file.lastPathComponent) func: checkFuncTime END】----------")
    }
}

首先来看下通过基本的递归来实现斐波那契数列

func fib1(_ n: Int) -> Int {
    if (n <= 1) {
        return n
    }
    return fib1(n - 1) + fib1(n - 2)
}


调试:
TimeTool.checkFuncTime {
    fib1(45)
}

运行结果:
----------【file: main.swift func: checkFuncTime START】----------
----------【file: main.swift func: checkFuncTime 耗时 19秒】----------
----------【file: main.swift func: checkFuncTime END】----------

接下来通过for...in和while来分别实现斐波那契数列,下列方法实现思路基本是一样的。

// 方法二: for...in
func fib2(_ n: Int) -> Int {
    if (n <= 1) {
        return n
    }
    var first = 0
    var second = 1
    
    for _ in 0..<n-1 {
        let sum = first + second
        first = second
        second = sum
    }
    return second
}

调试:
TimeTool.checkFuncTime {
    fib2(45)
}

运行结果:
----------【file: main.swift func: checkFuncTime START】----------
----------【file: main.swift func: checkFuncTime 耗时 0】----------
----------【file: main.swift func: checkFuncTime END】----------




// 方法三: while
func fib3(_ n: Int) -> Int {
    if (n <= 1) {
        return n
    }
    var first = 0
    var second = 1
    
    var total = n
    while total > 1 {
        let sum = first + second
        first = second
        second = sum
        total -= 1
    }
    return second
}

调试:
TimeTool.checkFuncTime {
    fib3(45)
}

运行结果:
----------【file: main.swift func: checkFuncTime START】----------
----------【file: main.swift func: checkFuncTime 耗时 0】----------
----------【file: main.swift func: checkFuncTime END】----------




// 方法四:: while
func fib4(_ n: Int) -> Int {
    if (n <= 1) {
        return n
    }
    var first = 0
    var second = 1
    
    var total = n
    while total > 1 {
        second += first;
        first = second - first;
        total -= 1
    }
    return second
}

调试:
TimeTool.checkFuncTime {
    fib4(45)
}

运行结果:
----------【file: main.swift func: checkFuncTime START】----------
----------【file: main.swift func: checkFuncTime 耗时 0】----------
----------【file: main.swift func: checkFuncTime END】----------

通过上述方法分析可见,通过递归实现斐波那契数列是非常耗时的。究其原因,是因为时间复杂度的问题。

斐波那契数列递归时间复杂度O(n²).png

斐波那契数列递归时间复杂度O(2^n)

fib(6) = 2^0 + 2^1 + 2^2 + 2^3 + (2^4 - 6) = 2^(n-6) + 2^(n-5) + 2^(n-4) + 2^(n-3) + (2^(n-2) - 6) 也是符合时间复杂度O(2^n)的。

方法二~四时间复杂度是O(n)

时间复杂度:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

注意:上述方法如果n过大,超过Int最大值,返回值就会溢出,这里只是比较不同方法执行效率问题,其他的不做多考虑。