leetcode 375 猜数字大小II
一、题目描述
二、解题思路
解法一:深度优先搜索
(1)函数功能:dfs函数用于返回[left,right]区间内,获得游戏胜利的最少钱数;
(2)递归出口:
如果left==right,表示找到了叶子节点,也就是猜到了这个数字,不用给钱,直接返回0就行。如果left>right,表示该区间里没有数字,直接返回0。所以,if(left>=right) ,return 0即可。
(3)函数体:
1>变量ret用于记录最终的返回值,初始化为INT_MAX;
2>从left开始循环枚举;
3>l用于记录(left,head-1)区间所需的钱数,r用于记录(head+1,right)区间所需的钱数,head+max(l,r)即为从head开始猜测需要用的最少的钱数;
4>每次循环结束,如果当前的head+max(r,l)小于等于ret,就更新ret,循环结束后得到的ret,即为符合题意的最小的金额。
解法二:记忆化搜索(优化)
解法一存在大量的重复计算,导致复杂度高,运行超时。我们可以采用记忆化搜索的方法来优化解法一。memo数组初始化为0,在dfs函数中:
(1)如果memo[left][right]!=0,表示这个值已经算过了,直接返回memo[left][right]即可(写在递归出口之后);
(2)在每次返回ret之前,把memo[left][right]更新一下。
三、代码实现
解法一:深度优先搜索(超时)
class Solution {
public:int getMoneyAmount(int n) {return dfs(1,n);}int dfs(int left,int right){//递归出口if(left>=right) return 0;int ret=INT_MAX;for(int head=left;head<=right;head++){int l=dfs(left,head-1);int r=dfs(head+1,right);ret=min(ret,max(l,r)+head);}return ret;}
};
解法二:记忆化搜索
class Solution {//记忆化搜索int memo[201][201]={0};
public:int getMoneyAmount(int n) {return dfs(1,n);}int dfs(int left,int right){//递归出口if(left>=right) return 0;if(memo[left][right]!=0) return memo[left][right];int ret=INT_MAX;for(int head=left;head<=right;head++){int l=dfs(left,head-1);int r=dfs(head+1,right);ret=min(ret,max(l,r)+head);}memo[left][right]=ret;return ret;}
};