为什么Swap Dictionary在Memoization期间比Array更慢

时间:2017-05-14 20:24:01

标签: arrays swift dictionary hashtable memoization

我正在进行算法挑战,并使用memoization来加速重复的递归调用。记忆最快的方法是使用哈希表(当值的范围很大,但输入在整个范围内是稀疏的)。我已经读过Dictionary是快速的哈希表。所以我实现了这样的memoization类:

fileprivate class MemoizationSlow { //Why is this so much slower?
    private var memDict = Dictionary<Int,Dictionary<Int,Int>>()
    func getResult(forAmount n:Int, numberOfCoins size:Int) -> Int? {
        return memDict[n]?[size];
    }
    func memoize(result:Int, amount n:Int, numberOfCoins size:Int) {
        memDict[n] = [size:result]
    }
}

而我发现这实际上是比蛮力更快!我知道这不是我的算法,也不是代码中其他地方的错误,因为我将memoization类更改为:

fileprivate class Memoization {
    private var memArr:Array<Array<Int?>>
    init(totalAmount:Int, coinsCount:Int) {
        memArr = Array<Array<Int?>>(repeating: Array<Int?>(repeating: nil, count: coinsCount), count: totalAmount+1)
    }
    func getResult(forAmount n:Int, numberOfCoins size:Int) -> Int? {
        return memArr[n][size]
    }
    func memoize(result:Int, amount n:Int, numberOfCoins size:Int) {
        memArr[n][size] = result
    }
}

算法闪电般快!第二种方法的唯一问题是它需要比散列表更多的空间复杂度,因为并非所有值都被记忆化。

我的一个重要问题是:为什么Dictionary实施比Array实施慢得多?

1 个答案:

答案 0 :(得分:1)

您的部分问题是,每次添加具有该金额的新值时,您的字典实现都会清除给定金额n的先前值。您应该将值添加到内部字典中,而不是使用仅包含新值的新字典替换内部字典。

试试这个:

func memoize(result:Int, amount n:Int, numberOfCoins size:Int) {
    // Get inner dictionary or use an empty one if there isn't one yet
    var inner = memDict[n] ?? [:]

    // Add the value to the inner dictionary
    inner[size] = result

    // Replace inner dictionary with the updated one
    memDict[n] = inner
}

或者,你可以这样做:

func memoize(result:Int, amount n:Int, numberOfCoins size:Int) {
    if memDict[n] != nil {
        memDict[n]![size] = result
    } else {
        memDict[n] = [size : result]
    }
}

留给读者的练习是找出哪一个更快。