这是力扣的一条题目:
不太会的可以自己去看题解,里边讲的很详细。
我这里主要写下我自己从递归一直优化到动态规划(空间优化)的历程。(代码可以通过力扣的oj)
递归:
1 class Solution {
2 public:
3 int dfs(vector<int>&nums,int left,int right)
4 {//这里dfs的意义是当前操作的玩家分数与另一个玩家的分数之差
5 if(left == right)
6 return nums[left];
7 return max(nums[left] - dfs(nums,left+1,right),nums[right]-dfs(nums,left,right-1));
8 }//由于"玩家的玩法都会使他的分数最大化,所以当前玩家尽量选择自己比对方分数高的策略
9 bool PredictTheWinner(vector<int>& nums) {
10 return dfs(nums,0,nums.size()-1) >=0;//自己的分数与对方的分数之差不小于0.则自己的分数不小于对方的分数
11 }
12 };
时间效率很低,于是进行升级:
记忆化递归:
1 class Solution {
2 public:
3 int memory[20][20];//既然数据范围已经给定了那么直接定义数组大小
4 int dfs(vector<int>&nums,int left,int right)
5 {//这里dfs的意义是当前操作的玩家分数与另一个玩家的分数之差
6 if(memory[left][right]!=-1)
7 return memory[left][right];
8 if(left == right)
9 {
10 memory[left][right]=nums[left];
11 return nums[left];
12 }
13 int ans = max(nums[left] - dfs(nums,left+1,right),nums[right]-dfs(nums,left,right-1));
14 memory[left][right] = ans;
15 return ans;
16 }//由于"玩家的玩法都会使他的分数最大化,所以当前玩家尽量选择自己比对方分数高的策略
17 bool PredictTheWinner(vector<int>& nums) {
18 memset(memory,-1,sizeof(memory));
19 return dfs(nums,0,nums.size()-1) >=0;//自己的分数与对方的分数之差不小于0.则自己的分数不小于对方的分数
20 }
21 };
效率大大提高
然后通过总结递归的递推公式,不难联想到用动态规划代替递归:
动态规划:
1 class Solution {
2 public:
3 int dp[20][20];
4 bool PredictTheWinner(vector<int>& nums) {
5 for(int i = 0;i<nums.size();++i)
6 {
7 dp[i][i] = nums[i];//初始化
8 }
9 for(int step = 1;step<nums.size();++step)
10 {
11 for(int i = 0;i+step<nums.size();++i)
12 {
13 int j = i + step;
14 dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1]); //建议结合表格理解
15 }
16 }
17 return dp[0][nums.size()-1] >=0;
18 }
19 };
虽然原理相同,但是递归便于理解,动态规划代码优雅。
其实动态规划的代码还可以更加优雅!通过优化,dp数组可以减少至一维,进一步减少内存需求。
动态规划(空间优化版):
1 class Solution {
2 public:
3 int dp[20];
4 bool PredictTheWinner(vector<int>& nums) {
5 for(int i = 0;i<nums.size();++i)
6 {
7 dp[i]= nums[i];//初始化
8 }
9 for(int step = 1;step<nums.size();++step)
10 {
11 for(int i = 0;i+step<nums.size();++i)
12 {
13 int j = i + step;
14 dp[i]=max(nums[j]-dp[i],nums[i]-dp[i+1]); //建议结合表格理解
15 }
16 }
17 return dp[0] >=0;
18 }
19 };
这下代码就非常之nice
总结:
在一般思路的基础上不断精进。