力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家
文章目录
- 一、递归
- 二、区间动态规划
LeetCode:486. 预测赢家

一、递归
注意到本题数据范围为 1 < = n < = 20 1<=n<=20 1<=n<=20,因此可以使用递归枚举选择方式,时间复杂度为 2 20 = 1024 ∗ 1024 = 1048576 = 1.05 × 1 0 6 2^{20} = 1024*1024=1048576=1.05 × 10^6 220=1024∗1024=1048576=1.05×106。
对于每一个先手都有两种选择方式,我们对该选择方式进行枚举。
我们定义递归函数 p r e d i c t predict predict表示玩家1在当前选择的情况下是否可以胜利,注意到每个玩家的玩法都会使他的分数最大化,因此对于玩家2的选择,如果存在一个选择使得玩家1输,那么该情况下玩家1都不能胜利(只要玩家2选择让自己赢的情况,那么玩家1就不能赢了)。但是对于玩家1的选择,存在一个选择能赢就算可以赢。

class Solution {
public:bool predictTheWinner(vector<int>& nums) {return predict(nums, 0, (int) nums.size() - 1, 0, 0, 0);}
private:bool predict(vector<int> & nums, int left, int right, int player, int score_1, int score_2){if(left > right){if(score_1 >= score_2) return true;else return false;}if(player == 0){//玩家一,存在一个赢就算赢了if(predict(nums, left + 1, right, player ^ 1, score_1 + nums[left], score_2)) return true;if(predict(nums, left, right - 1, player ^ 1, score_1 + nums[right], score_2)) return true;}else{//玩家二,存在一个玩家二赢,则玩家一必输。if(predict(nums, left + 1, right, player ^ 1, score_1, score_2 + nums[left]) &&predict(nums, left, right - 1, player ^ 1, score_1, score_2 + nums[right])) return true;}return false;}
};
二、区间动态规划
注意到这里是从大的数组中选择,让数组依次减小,我们也可以从数组小的开始转移到大数组,因为当小数组确定时,大数组也能确定。
我们可以定义 d p 1 [ i ] [ j ] [ p l a y e r ] dp1[i][j][player] dp1[i][j][player]表示在选择数组 [ i , j ] [i,j] [i,j]时, p l a y e r player player先手时,玩家1的分数;类似的有 d p 2 [ i ] [ j ] [ p l a y e r ] dp2[i][j][player] dp2[i][j][player]。
则有状态转移:
//玩家1先手dp1[i][j][0] = max(dp1[i + 1][j][1] + nums[i], dp1[i][j - 1][1] + nums[j]);if(dp1[i + 1][j][1] + nums[i] >= dp1[i][j - 1][1] + nums[j]){dp2[i][j][0] = dp2[i + 1][j][1];if(dp1[i + 1][j][1] + nums[i] == dp1[i][j - 1][1] + nums[j])dp2[i][j][0] = min(dp2[i + 1][j][1], dp2[i][j - 1][1]);}else{dp2[i][j][0] = dp2[i][j - 1][1];}
//玩家2先手dp2[i][j][1] = max(dp2[i + 1][j][0] + nums[i], dp2[i][j - 1][0] + nums[j]);if(dp2[i + 1][j][0] + nums[i] >= dp2[i][j - 1][0] + nums[j]){dp1[i][j][1] = dp1[i + 1][j][0];if(dp2[i + 1][j][0] + nums[i] == dp2[i][j - 1][0] + nums[j])dp1[i][j][1] = min(dp1[i + 1][j][0], dp1[i][j - 1][0]);}else{dp1[i][j][1] = dp1[i][j - 1][0];}
时间复杂度: O ( N 2 ) O(N^2) O(N2)

class Solution {
public:bool predictTheWinner(vector<int>& nums) {vector<vector<array<int, 2>>> dp1(nums.size(), vector<array<int, 2>>(nums.size(), array<int, 2>{}));vector<vector<array<int, 2>>> dp2(nums.size(), vector<array<int, 2>>(nums.size(), array<int, 2>{}));for(int i = 0; i < nums.size(); ++ i){dp1[i][i][0] = nums[i];dp2[i][i][1] = nums[i];}for(int k = 1; k < nums.size(); ++ k){for(int i = 0; k + i < nums.size(); ++ i){int j = i + k;//玩家1先手dp1[i][j][0] = max(dp1[i + 1][j][1] + nums[i], dp1[i][j - 1][1] + nums[j]);if(dp1[i + 1][j][1] + nums[i] >= dp1[i][j - 1][1] + nums[j]){dp2[i][j][0] = dp2[i + 1][j][1];if(dp1[i + 1][j][1] + nums[i] == dp1[i][j - 1][1] + nums[j])dp2[i][j][0] = min(dp2[i + 1][j][1], dp2[i][j - 1][1]);}else{dp2[i][j][0] = dp2[i][j - 1][1];}//玩家2先手dp2[i][j][1] = max(dp2[i + 1][j][0] + nums[i], dp2[i][j - 1][0] + nums[j]);if(dp2[i + 1][j][0] + nums[i] >= dp2[i][j - 1][0] + nums[j]){dp1[i][j][1] = dp1[i + 1][j][0];if(dp2[i + 1][j][0] + nums[i] == dp2[i][j - 1][0] + nums[j])dp1[i][j][1] = min(dp1[i + 1][j][0], dp1[i][j - 1][0]);}else{dp1[i][j][1] = dp1[i][j - 1][0];}}}return dp1[0][(int) nums.size() - 1][0] >= dp2[0][(int) nums.size() - 1][0];}
};
简化代码:(这个代码过了)
简化逻辑:玩家1先手,那么玩家1效益最大,玩家2应该效益要最低。
但这个逻辑感觉存在一定问题,因为玩家1先手,玩家1想要自己的效益最大,这个时候玩家2的效益是跟玩家1的选择有关的,因为棋局完全根据玩家1来决定。所以一开始我并没有直接使用min求解后手。
class Solution {
public:bool predictTheWinner(vector<int>& nums) {vector<vector<array<int, 2>>> dp1(nums.size(), vector<array<int, 2>>(nums.size(), array<int, 2>{}));vector<vector<array<int, 2>>> dp2(nums.size(), vector<array<int, 2>>(nums.size(), array<int, 2>{}));for(int i = 0; i < nums.size(); ++ i){dp1[i][i][0] = nums[i];dp2[i][i][1] = nums[i];}for(int k = 1; k < nums.size(); ++ k){for(int i = 0; k + i < nums.size(); ++ i){int j = i + k;//玩家1先手dp1[i][j][0] = max(dp1[i + 1][j][1] + nums[i], dp1[i][j - 1][1] + nums[j]);dp2[i][j][0] = min(dp2[i + 1][j][1], dp2[i][j - 1][1]);//玩家2先手dp2[i][j][1] = max(dp2[i + 1][j][0] + nums[i], dp2[i][j - 1][0] + nums[j]);dp1[i][j][1] = min(dp1[i + 1][j][0], dp1[i][j - 1][0]);}}return dp1[0][(int) nums.size() - 1][0] >= dp2[0][(int) nums.size() - 1][0];}
};
相关文章:
力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家
文章目录 一、递归二、区间动态规划 LeetCode:486. 预测赢家 一、递归 注意到本题数据范围为 1 < n < 20 1<n<20 1<n<20,因此可以使用递归枚举选择方式,时间复杂度为 2 20 1024 ∗ 1024 1048576 1.05 1 0 6 2^{20…...
黑白格
题目描述 小杨有一个 n 行 m 列的网格图,其中每个格子要么是白色,要么是黑色。 小杨想知道至少包含 k 个黑色格子的最小子矩形包含了多少个格子。 输入格式 第一行包含三个正整数 n,m,k,含义如题面所示。 之后 n 行,每行⼀个…...
数据链路层(MAC地址)
文章目录 数据链路层(MAC地址)1、以太网2、以太网帧格式3、MAC地址4、对比理解 MAC 地址和 IP 地址5、最大传输单元(MTU)6、MTU 对 IP 协议的影响7、MTU 对 UDP 协议的影响8、MTU 对 TCP 协议的影响9、查看硬件地址和 MTU10、ARP …...
【ruby java】登陆功能/邮件发送模版240903
Rails 风格登录系统添加全面而详细的注释,解释每个部分的功能和用途。 详细注释,解释了每个文件和代码块的功能。以下是一些关键点的总结: 1. 控制器(Controllers): - ApplicationController: …...
告别格式不兼容烦恼!ape转换mp3,分享3个简单方法
各位读者们,你们是否有过这种体验:满怀期待地在网上下载一首好听的歌曲,结果怎么点击手机都播放不了,定睛一看,弹窗显示“无法播放该音频文件”。这是为什么呢?原来那首歌的音频格式是ape,不被手…...
Java核心知识体系-并发与多线程:线程基础
1 先导 Java线程基础主要包含如下知识点,相信我们再面试的过程中,经常会遇到类似的提问。 1、线程有哪几种状态? 线程之间如何转变? 2、线程有哪几种实现方式? 各优缺点? 3、线程的基本操作(线程管理机制ÿ…...
KRaft模式下的Kafka启动指南:摆脱Zookeeper依赖
一、背景介绍 多年来,人们一直在同时使用Apache ZooKeeper和Apache Kafka。但是自Apache Kafka 3.3发布以来,它就可以在没有ZooKeeper的情况下运行。同时它包含了新的命令kafka-metadata-quorum和kafka-metadata-shell?该如何安装新版kafka,…...
【数据库】MySQL-基础篇-函数
专栏文章索引:数据库 有问题可私聊:QQ:3375119339 目录 一、简介 二、字符串函数 三、数值函数 四、日期函数 五、流程函数 一、简介 函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着,这一段程序或代码在 M…...
dp练习【4】
最长数对链 646. 最长数对链 给你一个由 n 个数对组成的数对数组 pairs ,其中 pairs[i] [lefti, righti] 且 lefti < righti 。 现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 [c, d] 才可以跟在 p1 [a, b…...
php 实现推荐算法
在PHP中实现推荐算法的应用场景通常包括电商、社交媒体、内容平台等。推荐算法可以帮助用户找到与其兴趣相关的内容,提高用户体验和平台黏性。以下是几种常见的推荐算法及其PHP实现方式: 1. 基于协同过滤的推荐算法 协同过滤(Collaborative…...
相机光学(三十六)——光圈
0.参考链接 (1)Hall光圈和Piris光圈的区别 (2)自动光圈及P-IRIS原理 1.光圈分类 Hall光圈和Piris光圈是两种不同的光圈技术。它们之间的区别如下: Hall光圈:Hall光圈是一种传统的光电子元件,通…...
数据结构——树和二叉树
目录 一、树的概念 二、树结点之间的关系 三、二叉树 1、满二叉树 2、完全二叉树 四、二叉树的存储 1、顺序存储 2、链式存储 一、树的概念 如果数据和数据之间满足一对多的关系,将其逻辑结构称之为树 如下图:树的根与树的分支存在一对多的关系 将上…...
142. Go操作Kafka(confluent-kafka-go库)
文章目录 Apache kafka简介开始使用Apache Kafka构建生产者构建消费者 总结 之前已经有两篇文章介绍过 Go如何操作 kafka 28.windows安装kafka,Go操作kafka示例(sarama库) 51.Go操作kafka示例(kafka-go库) Apache ka…...
spring boot(学习笔记第十九课)
spring boot(学习笔记第十九课) Spring boot的batch框架,以及Swagger3(OpenAPI)整合 学习内容: Spring boot的batch框架Spring boot的Swagger3(OpenAPI)整合 1. Spring boot batch框架 Spring Batch是什么 Spring Batch 是一个…...
docker安装 redis 并且加密开启SSL/TLS通道
拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/redis:latest docker tag registry.cn-hangzhou.aliyuncs.com/qiluo-images/redis:latest redis:latest要在 Docker 容器中启动 Redis 并开启 SSL/TLS 加密,需按照以下步骤修改启动命令和配置…...
什么是ARM架构?什么是X86架构?两者的区别是什么?
一、什么是ARM架构 (一)起源于发展 ARM 架构由英国剑桥的 Acorn 计算机公司开发。因市场无合适产品,Acorn 自行设计出第一款微处理器,命名为 ARM。此后 ARM 架构不断发展,1990 年为与苹果合作成立 ARM 公司࿰…...
【vscode】vscode paste image插件设置
本文首发于 ❄️慕雪的寒舍 vscode编辑md文件的时候,如果想插入图片,自带的粘贴只会粘贴到当前目录下,也没有文件重命名,很不友好。 在扩展商店里面有mushan的Paste Image插件,相比自带的,更加友好一点。但…...
自定义string类
#include <iostream> #include <string> int main() { std::string str "Hello, World!"; // 使用 c_str() 将 std::string 转换为 C 风格字符串,并传递给 printf printf("The string is: %s\n", str.c_str()); // 尝试修改…...
Python | Leetcode Python题解之第387题字符串中的第一个唯一字符
题目: 题解: class Solution:def firstUniqChar(self, s: str) -> int:position dict()q collections.deque()n len(s)for i, ch in enumerate(s):if ch not in position:position[ch] iq.append((s[i], i))else:position[ch] -1while q and po…...
RocketMQ 消费时序列化报错问题分析及解决
问题背景 在2024年3月7日,系统消费 RocketMQ 消息时出现了序列化报错,错误信息显示为: java.io.InvalidClassException: com.xxx.xxx.bean.mg.GoodsChangeLogMessage; local class incompatible: stream classdesc serialVersionUID... 这是…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
