《预测赢家》—从递归到动态规划的优化之路

RISC-V— 架构基础知识学习 蜂鸟 E200 系列是一个开源的RISC-V 处理器。蜂鸟 E200 系列由中国大陆研发团队开发,用户能够轻松与开发人员取得交流和支持。RI蜂鸟 E200 处理器研发团队拥有在国际一流公司多年开发处理器的经验,使用稳健的Verilog 2001 语法编写的可综合 RTL 代码,以工业级标准进行开发。蜂鸟 E200 的代码为人工编写,添加丰富的注释且可读性强,非常易于理解。 阅读详情

目录

题目:

递归:

记忆化递归:

动态规划:

动态规划(空间优化版):

总结: 


题目:

这是力扣的一条题目:

给定一个表示分数的非负整数数组。玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿....每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为嬴家。你可以假设每个玩家的玩法都会使他的分数最大化。
 

不太会的可以自己去看题解,里边讲的很详细。

我这里主要写下我自己从递归一直优化到动态规划(空间优化)的历程。(代码可以通过力扣的oj)

递归:

class Solution {
public:
    int dfs(vector<int>&nums,int left,int right)
    {//这里dfs的意义是当前操作的玩家分数与另一个玩家的分数之差
        if(left == right)
            return nums[left];
        return max(nums[left] - dfs(nums,left+1,right),nums[right]-dfs(nums,left,right-1));
    }//由于"玩家的玩法都会使他的分数最大化,所以当前玩家尽量选择自己比对方分数高的策略
    bool PredictTheWinner(vector<int>& nums) {
            return dfs(nums,0,nums.size()-1) >=0;//自己的分数与对方的分数之差不小于0.则自己的分数不小于对方的分数
    }
};

 时间效率很低,于是进行升级:

记忆化递归:

class Solution {
public:
    int memory[20][20];//既然数据范围已经给定了那么直接定义数组大小
    int dfs(vector<int>&nums,int left,int right)
    {//这里dfs的意义是当前操作的玩家分数与另一个玩家的分数之差
        if(memory[left][right]!=-1)
            return memory[left][right];
        if(left == right)
            {
            memory[left][right]=nums[left];
            return nums[left];
            }
        int ans =  max(nums[left] - dfs(nums,left+1,right),nums[right]-dfs(nums,left,right-1));
        memory[left][right] = ans;
        return ans;
    }//由于"玩家的玩法都会使他的分数最大化,所以当前玩家尽量选择自己比对方分数高的策略
    bool PredictTheWinner(vector<int>& nums) {
            memset(memory,-1,sizeof(memory));
            return dfs(nums,0,nums.size()-1) >=0;//自己的分数与对方的分数之差不小于0.则自己的分数不小于对方的分数
    }
};

效率大大提高

然后通过总结递归的递推公式,不难联想到用动态规划代替递归:

动态规划:

 

class Solution {
public:
    int dp[20][20];
    bool PredictTheWinner(vector<int>& nums) {
        for(int i = 0;i<nums.size();++i)
        {
            dp[i][i] = nums[i];//初始化
        }
        for(int step = 1;step<nums.size();++step)
        {
            for(int i = 0;i+step<nums.size();++i)
            {
                int j = i + step;
                dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1]); //建议结合表格理解
            }
        }
        return dp[0][nums.size()-1] >=0;
    }
};

虽然原理相同,但是递归便于理解,动态规划代码优雅。

其实动态规划的代码还可以更加优雅!通过优化,dp数组可以减少至一维,进一步减少内存需求。

动态规划(空间优化版):

class Solution {
public:
    int dp[20];
    bool PredictTheWinner(vector<int>& nums) {
        for(int i = 0;i<nums.size();++i)
        {
            dp[i]= nums[i];//初始化
        }
        for(int step = 1;step<nums.size();++step)
        {
            for(int i = 0;i+step<nums.size();++i)
            {
                int j = i + step;
                dp[i]=max(nums[j]-dp[i],nums[i]-dp[i+1]); //建议结合表格理解
            }
        }
        return dp[0] >=0;
    }
};

 这下代码就非常之nice

执行结果:


总结: 

        在一般思路的基础上不断精进。

开心消消乐 1)当点击一个1时,该1变被反转为0,同时相邻的上、下、左、右,以及左上、左下、右上、右下8个方向的1(如果存在1)均会自动反转为0;2)进一步地,一个位置上的1被反转为0时,与其相邻的8个方向的1(如果存在1)均会自动反转为0;上述样例中,四个角上的1均在中间的1的相邻8个方向上,因此只需要点击一次即可。给定一个N行M列的二维矩阵,矩阵中每个位置的数字取值为0或1。在上述4 * 4的矩阵中,只需要点击2次,即可将所有的1进行消除。接下来N行表示矩阵的初始值,每行均为M个数,取值范围[0,1] 阅读详情

相关推荐

在 Linux 虚拟机中手动安装 VMware Tools

对于 Linux 虚拟机,您可以从命令行手动安装 VMware Tools。对于 Linux 的较高发行版,请使用集成的 open-vm-tools 版本。 前提条件 有关 open-vm-tools 的操作系统兼容性的详细信息,请参见《VMware 兼容性指南》,网址为VMware Compatibility Guide - System Search。 开启虚拟机。 确认客户机操作系统正在运行。 因为 VMware Tools 安装程序是使用 Perl 编写的,请确认已在客户机操作系统中安..

m0_62526815的博客 1755

算法 预测赢家(动态规划)

文章目录前言一、题意解析二、动态规划 前言 题目链接 给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。 玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0 。每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。 如果玩家 1 能成为赢家,返回 true 。

weixin_42109053的博客 1496

Synares病毒实战:如何手动清除C盘隐藏的Synaptics.exe(附资源修复脚本)

本文详细介绍了Synares感染型病毒的手动清除方法,该病毒伪装成Synaptics触摸板驱动,感染EXE和XLSX文件。文章提供了从病毒行为分析、母体清除到被感染文件修复的全流程指南,并附有实用的资源修复脚本和防御加固方案,帮助用户彻底清除这一顽固病毒。

lg888的博客 2343

算法刷题打卡第32天:预测赢家---动态规划

预测赢家 难度:中等 给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。 玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0 。每一回合,玩家从数组的任意一端取一个数字,取到的数字将会从数组中移除。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。 如果玩家 1 能成为赢家,返回 true 。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 true 。你可以假设每个玩家的玩法都会使他的分数最大化。

weixin_45616285的博客 601

Halcon图片拼接避坑指南:特征点匹配常见问题与解决方案

本文深入解析Halcon图片拼接中特征点匹配的常见问题与解决方案,涵盖特征点提取、匹配优化及变换模型选择等关键环节。针对工业视觉检测中的拼接错位、重影等问题,提供参数调优、图像预处理和算法选择等实战技巧,帮助开发者高效避坑并提升拼接精度。

weixin_28694169的博客 198

Android13系统设置第三方app为设备所有者

DevicePolicyManagerService.java文件所在目录是frameworks/base,记得将包类名换成自己app的。2. 将拷贝到系统分区下的两个xml文件继续通过init.rc服务拷贝到data/system/目录下并修改权限。1. 拷贝设备所有者和设备管理器两个对应的xml文件到系统分区。

wzh048503的博客 2503

486 预测赢家(递归、动态规划)

1. 问题描述: 给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。 示例 1: 输入:[1, 5, 2] 输出:False 解释:一开始,玩家1可以从1和2中进行选择。 如果他选择 2(或者 1

二哈 512

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

WW、forever的博客 195

第486题 预测赢家(递归+动态规划)

预测赢家(递归+动态规划)

rygy_的博客 1192

RepHead一种重参数化检测头用于提升YOLOv8在困难样本上的检测性能

在目标检测任务中,困难样本通常是指那些由于特殊背景、遮挡、低分辨率或极度小物体等因素,导致模型难以识别的样本。这类样本对传统YOLO系列模型的影响较大,常常造成漏检或误检。重参数化(Reparameterization)是一种深度学习中常用的技术,旨在通过对网络参数的变换,使得模型在训练过程中能够更加灵活地适应不同的数据特征。通过对原始网络结构的参数进行重新表达,能够引导模型在训练过程中学习到更加有效的特征。本文详细介绍了YOLOv8的改进——RepHead检测头,并深入分析了它在解决困难样本检测中的应用。

博客 1209

基于YOLO26深度学习框架的人脸识别门禁系统的算法研究实现方法

本文研究了基于YOLO26深度学习框架的人脸识别门禁系统实现方法。系统采用YOLO26目标检测算法,通过CSPDarknet53主干网络、特征金字塔结构和注意力机制实现高效人脸检测。研究内容包括数据预处理、模型训练优化和身份验证等关键技术,使用迁移学习策略和CIoU损失函数提升检测精度。该系统可应用于智能安防场景,具有实时性强、识别准确的特点,为门禁管理提供了智能化解决方案。

一键难忘的博客 766

预测赢家-子游戏【动态规划dp】

如果是石子游戏这道题就是先手必赢的 解法1:递归 思路: public static void main(String[] args) { int[] array=new int[]{5,200,2,3,1}; //模拟石子游戏,堆数为偶,先手必赢 //int[] array=new int[]{5,200,2,3,1};//堆数为5是奇数 先手必输 int sum=0; for (int i : array) { ..

QAQ 340

论文必备 - YOLOv11热力图可视化,支持指定模型,指定显示层,设置置信度,以及10种可视化实现方式

本文带来的是YOLOv11热力图可视化功能,支持,以及。我们经常看到一些论文里绘制了不同的热力图,一方面能够直观的感受其模型的有效性,另一方面也丰富了论文内容。特别是在使用了注意力模块的网络中,热力图就可以验证注意力机制是否真正聚焦到了预期的重要特征上,以便对模型的有效性和合理性进行评估。例如这篇文章中展示的,就很能够表达作者改进后的模型相比之前模型的优越性。

Limiiiing的博客 5504

LeetCode486-预测赢家

LeetCode486-预测赢家 题目 给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。 给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化 输入:[1, 5, 2] 输出:False 解释:一开始,玩家1可以从1和2中进行选择。 如果他选择 2(或者

viva_la__vida的博客 206

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

算法题 预测赢家

算法题 预测赢家

红血哥 546

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

一天一大 lee(预测赢家)难度:中等-Day20200901

题目: 给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。 每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。 给定一个表示分数的数组,预测玩家 1 是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。 示例: 示例 1 输入:[1, 5, 2] 输出:False 解释:一开始,玩家1可以从1和2中进行选择。 如果他选择 2(或者 .

坑人的小书童 264

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

每日算法总结——动态规划练习:预测赢家、象棋马走日、零钱兑换、动态规划总结

首先,需要找到一个尝试的版本,即暴力递归的版本尝试的方式可以是从左往右(从右往左)尝试范围尝试等等(这两个是比较常见的尝试模型,基本可以搞定七成以上的题目)暴力递归转记忆化搜索这个过程比较容易,就是分析递归函数有几个变量,然后决定用几维数组来存储搜索结果记忆化搜索转严格表结构动态规划首先,考虑 Base case 的情况,把能直接得到值的位置先填到表格里分析递归过程,搞清楚表格之间的依赖关系,从而确定表格的填写顺序优化填写过程遍历表格是必须的,无法优化;

qq_53661372的博客 290

力扣 (区间 dp 专题1)

定义 区间 dp[left][right],首先我们要明确最终要求的是 dp[0][n - 1]。很容易想到动态规划,但从递归入手为优解。首先要知道递归出口,也就是基础情况:只剩一个字符,必为回文,不动;剩两个字符,相同字符则回文,不动,不同只需操作一次即可;一般情况的讨论其实也简单,就不赘述了,直接上代码递归 + 记忆化搜索当然可以进行空间优化,一维数组滚动,很机械化,写了很多遍了,, 第一题还是写一下吧。

一本苦涩的书 445

leedcode 486. 预测赢家 (区间dp)

leedcode486 题解

2403_87530627的博客 354

【leetcode刷题】九月leetcode打卡每日记录(持续更新)

文章目录[486. 预测赢家](https://leetcode-cn.com/problems/predict-the-winner/) 486. 预测赢家 算法1:递归 /* 递归: 定义get (int l,int r):先手玩家从数组[l,r]中能够拿取的最大 差值 如果l == r,那么只能拿取nums[l]; 如果l < r,那么可以拿取max(nums[l] - get(l +1,r), nums[r] - get(l,r+1))

py今天刷题了吗 630

LeetCode Predict the Winner

原题链接在这里:https://leetcode.com/problems/predict-the-winner/description/ 题目: Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array foll...

weixin_30628077的博客 77

LeetCode 486 预测赢家 1140 石子游戏|| (极小化极大、动态规划)

486. 预测赢家 记忆化搜索 class Solution { public: typedef pair<int,int> P; bool vis[22][22] = {0}; P dp[22][22]; bool PredictTheWinner(vector<int>& nums) { P p = dfs(nums,0,nums.size()-1); return p.first>=p.secon

SongyangJi 239

LeetCode刷题 day33

每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。最终,玩家 1(234 分)比玩家 2(12 分)获得更多的分数,所以返回 true,表示玩家 1 可以成为赢家。当i=j时,当前玩家只有一种选择,即nums[i],此时dp[i][i] = nums[i]

m0_37949220的博客 196

LeetCode 486. 预测赢家(记忆化搜索 / 动态规划)

LeetCode 链接 LeetCode 486 ps:最近发现记忆化搜索真的好用哈~~ 一、问题描述 给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。 给定一个表示分数的数组,预测玩家1是否会成为赢...

qq_36183146的博客 391

LeetCode每日一题(20200901)

原题地址: 思考过程: 假如使用穷举,时间复杂度是2^n,题目说到n最大为20,似乎可行。按此实现代码。 代码实现: public boolean PredictTheWinner1(int[] nums) { int left = 0, right = nums.length - 1; int sum1 = 0, sum2 = 0; return calc(nums, sum1, sum2, left, right, 0); ..

Payne_xy的博客 193

随手练——博弈论入门 leetcode - 486. Predict the Winner

题目链接:https://leetcode.com/problems/predict-the-winner/ 1.暴力递归 当前数组左边界:i,右边界:j; 对于先发者来说,他能取到的最大值是:max(arr[i] + second(arr, i + 1, j), arr[j] + second(arr, i, j - 1)); (arr[i] + 作为后发者,在 i+1 到 j 上取得的...

weixin_30539835的博客 148
上一篇: 探究“补阶乘大法的本质“——糖水不等式
下一篇: 程序设计中左闭右开区间的广泛应用
咖啡咖_CoffCa
博客等级 码龄6年 116粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡咖_CoffCa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值