Go语言 转换朴素递归硬币问题时发生记忆错误

yhxst69z  于 2022-12-25  发布在  Go
关注(0)|答案(1)|浏览(129)

我正在尝试以下问题:
两个玩家从一堆硬币开始,每个玩家都可以选择从这堆硬币中取出一个或两个硬币。取出最后一个硬币的玩家输。
我提出了以下简单的递归实现(playgound):

func gameWinner(coinsRemaining int, currentPlayer string) string {
    if coinsRemaining <= 0 {
        return currentPlayer
    }

    var nextPlayer string

    if currentPlayer == "you" {
        nextPlayer = "them"
    } else {
        nextPlayer = "you"
    }

    if gameWinner(coinsRemaining-1, nextPlayer) == currentPlayer || gameWinner(coinsRemaining-2, nextPlayer) == currentPlayer {
        return currentPlayer
    } else {
        return nextPlayer
    }
}

func main() {
  fmt.Println(gameWinner(4, "you")) // "them"
}

以上代码工作正常。
然而,当我通过实现记忆化(见下文,或on the playgound)来改进这个解决方案时,我得到了错误的答案。

func gameWinner(coinsRemaining int, currentPlayer string, memo map[int]string) string {
    if coinsRemaining <= 0 {
        return currentPlayer
    }

    var nextPlayer string

    if currentPlayer == "you" {
        nextPlayer = "them"
    } else {
        nextPlayer = "you"
    }

    if _, exists := memo[coinsRemaining]; !exists {
        if gameWinner(coinsRemaining-1, nextPlayer, memo) == currentPlayer || gameWinner(coinsRemaining-2, nextPlayer, memo) == currentPlayer {
            memo[coinsRemaining] = currentPlayer
        } else {
            memo[coinsRemaining] = nextPlayer
        }
    }

    return memo[coinsRemaining]
}

func main() {
    memo := make(map[int]string)
    fmt.Println(gameWinner(4, "you", memo))
}

如果能帮助我们理解为什么第二个实现返回的值与第一个不同,我们将不胜感激!

jvlzgdj9

jvlzgdj91#

你的记忆是错误的:赢家不仅取决于当前硬币的数量,还取决于轮到谁。2你需要如下的东西:

type state struct {
    coinsRemaining int
    currentPlayer string
}
memo := make(map[state]string)

相关问题