375. 猜数字大小 II

我们正在玩一个猜数游戏,游戏规则如下:
我从 1 n 之间选择一个数字,你来猜我选了哪个数字。
每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了。
然而,当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。直到你猜到我选的数字,你才算赢得了这个游戏。

  1. //错误方法,二分
  2. func getMoneyAmount(n int) int {
  3. left, right, guess, result := 1, n, n, 0
  4. for left <= right {
  5. mid := left + (right-left)/2
  6. if mid == guess {
  7. return result
  8. } else if mid < guess {
  9. left = mid + 1
  10. } else {
  11. right = mid - 1
  12. }
  13. result += mid
  14. }
  15. return result
  16. }
//实际考察动态规划
func getMoneyAmount(n int) int {
    dp := make([][]int, n+1)
    for k := range dp {
        dp[k] = make([]int, n+1)
    }
    for l := 2; l <= n; l++ {
        for left := 1; left+l-1 <= n; left++ {
            minValue := math.MaxInt32
            right := left + l - 1
            for piv := left; piv < right; piv++ {
                minValue = min(minValue, piv+max(dp[left][piv-1], dp[piv+1][right]))
            }
            dp[left][right] = minValue
        }
    }
    return dp[1][n]
}

func max(num1, num2 int) int {
    if num1 > num2 {
        return num1
    }
    return num2
}

func min(num1, num2 int) int {
    if num1 < num2 {
        return num1
    }
    return num2
}
//回溯法优化
var memo map[string]int

func getMoneyAmount(n int) int {
    memo = make(map[string]int)
    return dfs(1, n)
}

func dfs(left, right int) int {
    key := fmt.Sprintf("%d-%d", left, right)
    if value, ok := memo[key]; ok {
        return value
    }
    if left >= right {
        return 0
    }
    result := math.MaxInt32
    for i := left; i <= right; i++ {
        result = min(result, i+max(dfs(left, i-1), dfs(i+1, right)))
    }
    memo[key] = result
    return result
}

func max(num1, num2 int) int {
    if num1 > num2 {
        return num1
    }
    return num2
}

func min(num1, num2 int) int {
    if num1 < num2 {
        return num1
    }
    return num2
}