375.猜数字大小 II

103 阅读1分钟

题目:
我们正在玩一个猜数游戏,游戏规则如下:

  1. 我从 1 ****到 n 之间选择一个数字。
  2. 你来猜我选了哪个数字。
  3. 如果你猜到正确的数字,就会 赢得游戏 。
  4. 如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
  5. 每当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。如果你花光了钱,就会 输掉游戏 。

给你一个特定的数字 n ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。
算法:
方法一:动态规划
记忆化搜索是咋回事

func getMoneyAmount(n int) int {
	// dp表示取值范围位[i,j]时,猜对数字的最小代价
	// dp[i][j] = k + min(dp[i][k - 1], dp[i + 1][j])
	dp := make([][]int, n + 1)
	for i := range dp {
		dp[i] = make([]int, n + 1)
	}
	// i从小到大遍历的话,求dp[1][n]时,dp[n-1][n]还没有初始化,还是0
	for i := n; i > 0; i -- {
		for j := i + 1; j <= n; j ++ {
			// 这里时k = j的情况
			// dp[i][j] = max(j + dp[i][j - 1], j + dp[j + 1][j])
			//          = j + dp[i][j - 1]
			// for循环就不用处理j = k的情况了
			dp[i][j] = j + dp[i][j - 1]
			for k := i; k < j; k ++ {
				if i < j {
					dp[i][j] = min(dp[i][j], max(k + dp[i][k - 1], k + dp[k + 1][j]))
				}
			}
		}
	}
	return dp[1][n]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}