当前位置: 首页 > news >正文

LeetCode 2811. Check if it is Possible to Split Array【脑筋急转弯;前缀和+动态规划或记忆化DFS】中等

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

给你一个长度为 n 的数组 nums 和一个整数 m 。请你判断能否执行一系列操作,将数组拆分成 n 个 非空 数组。

在每一步操作中,你可以选择一个 长度至少为 2 的现有数组(之前步骤的结果) 并将其拆分成 2 个子数组,而得到的 每个 子数组,至少 需要满足以下条件之一:

  • 子数组的长度为 1 ,或者
  • 子数组元素之和 大于或等于  m 。

如果你可以将给定数组拆分成 n 个满足要求的数组,返回 true ;否则,返回 false 。

注意: 子数组是数组中的一个连续非空元素序列。

示例 1:

输入:nums = [2, 2, 1], m = 4
输出:true
解释:
第 1 步,将数组 nums 拆分成 [2, 2][1] 。
第 2 步,将数组 [2, 2] 拆分成 [2][2] 。
因此,答案为 true

示例 2:

输入:nums = [2, 1, 3], m = 5 
输出:false
解释:
存在两种不同的拆分方法:
第 1 种,将数组 nums 拆分成 [2, 1][3] 。
第 2 种,将数组 nums 拆分成 [2][1, 3] 。
然而,这两种方法都不满足题意。因此,答案为 false

示例 3:

输入:nums = [2, 3, 3, 2, 3], m = 6
输出:true
解释:
第 1 步,将数组 nums 拆分成 [2, 3, 3, 2][3] 。
第 2 步,将数组 [2, 3, 3, 2] 拆分成 [2, 3, 3][2] 。
第 3 步,将数组 [2, 3, 3] 拆分成 [2][3, 3] 。
第 4 步,将数组 [3, 3] 拆分成 [3][3] 。
因此,答案为 true

提示:

  • 1 <= n == nums.length <= 100
  • 1 <= nums[i] <= 100
  • 1 <= m <= 200

解法1 记忆化DFS/区间DP+前缀和

为了方便求出子数组的和,我们使用前缀和。

对于数组拆分,很自然地想到DFS,但如果每次都在数组两侧拆分,则复杂度可能到 O ( 2 100 ) O(2^{100}) O(2100) ,为此必须使用记忆化+DFS。我个人的写法如下所示,令 d f s ( l , r ) dfs(l, r) dfs(l,r) 表示区间 [ l , r ] [l,r] [l,r] 可否拆分:

  • 递归边界:区间长度 ≤ 2 \le 2 2 ,一定可拆分在区间长度 > 2 > 2 >2 且区间和 ≤ m \le m m 时,此时无论如何都无法继续拆分下去
  • 递归过程:只有区间和大于 m m m可以拆分出子区间 [ l + 1 , r ] [l + 1, r] [l+1,r] [ l , r − 1 ] [l, r - 1] [l,r1](对应区间长度为 1 1 1 或区间和 ≥ m \ge m m ),且满足子区间可拆分——即 d f s ( l + 1 , r ) = t r u e dfs(l + 1, r) = true dfs(l+1,r)=true d f s ( l , r − 1 ) = t r u e dfs(l, r - 1)= true dfs(l,r1)=true ,此时区间 [ l , r ] [l, r] [l,r] 可以拆分。
class Solution {
private:int m;int sum[110];int dp[110][110];int dfs(int l, int r) {if (dp[l][r] != -1) return dp[l][r]; // 已经有答案if (l + 1 >= r) return dp[l][r] = 1; // 拆分前进行判断,可以拆分if (sum[r + 1] - sum[l] <= m) return dp[l][r] = 0; // 拆分前进行判断,不可拆分int left = 0, right = 0;if (l + 1 == r || sum[r + 1] - sum[l + 1] >= m) // 看是否可以拆分出[l+1,r]这个子数组left = dfs(l + 1, r); // 看[l+1,r]子数组是否可继续拆分if (l == r - 1 || sum[r] - sum[l] >= m) // 看是否可以拆分出[l,r-1]这个子数组right = dfs(l, r - 1); // 看[l,r-1]子数组是否可继续拆分return dp[l][r] = left || right; }
public:bool canSplitArray(vector<int>& nums, int m) {this->m = m;memset(sum, 0, sizeof(sum));memset(dp, -1, sizeof(dp));int n = nums.size();for (int i = 0; i < n; ++i) sum[i + 1] = sum[i] + nums[i];return dfs(0, n - 1);}
};

还可使用区间DP:

class Solution {
public:bool canSplitArray(vector<int>& nums, int m) {int sum[110];bool dp[110][110];memset(sum, 0, sizeof(sum));memset(dp, false, sizeof(dp));int n = nums.size();for (int i = 0; i < n; ++i) sum[i + 1] = sum[i] + nums[i];// dp[i][j]表示区间[i,j]能否拆分for (int i = n - 1; i >= 0; --i) {dp[i][i] = true;if (i + 1 < n) dp[i][i + 1] = true;// 区间[i,j-1], [i+1,j]是否可拆for (int j = i + 2; j < n; ++j) {// [i,j]能否拆分为[i+1,j]或[i,j-1],看拆出子数组的和是否>=m,且拆出子数组是否可继续拆分if (sum[j] - sum[i] >= m && dp[i][j - 1]|| sum[j + 1] - sum[i + 1] >= m && dp[i + 1][j])dp[i][j] = true;        }}return dp[0][n - 1];}
};

解法2 脑筋急转弯(最优解法)

要善于将题目转换成另外一种解法,对题目的理解、数学逻辑要求较高。

  • 先特判 n ≤ 2 n \le 2 n2 的情况,这是满足要求的。
  • 对于 n ≥ 3 n\ge 3 n3 的情况,无论按照何种方式分割,一定会在某个时刻,分割出一个长为 2 2 2 的子数组
    • 如果 nums \textit{nums} nums 中任何长为 2 2 2 的子数组的元素和都小于 m m m ,那么无法满足要求
    • 否则,可以用这个子数组作为「核心」,像剥洋葱一样,一个一个地去掉 nums \textit{nums} nums 的首尾元素,最后得到这个子数组。由于子数组的元素和 ≥ m \ge m m ,所以每次分割出一个元素时,剩余的子数组的元素和也必然是 ≥ m \ge m m 的,满足要求。

于是本题可转换成:求数组中是否存在2个相邻元素之和 ≥ m \ge m m 。相信题目如果这么问,100%的人都能做出来。

class Solution {
public:bool canSplitArray(vector<int>& nums, int m) {int n = nums.size();for (int i = 1; i < n; ++i)if (nums[i - 1] + nums[i] >= m) return true;return n <= 2;}
};

相关文章:

LeetCode 2811. Check if it is Possible to Split Array【脑筋急转弯;前缀和+动态规划或记忆化DFS】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

【学习日记】【FreeRTOS】链表结构体及函数详解

写在前面 本文主要是对于 FreeRTOS 中链表相关内容的详细解释&#xff0c;代码大部分参考了野火FreeRTOS教程配套源码&#xff0c;作了一小部分修改。 一、结构体定义 主要包含三种结构体&#xff1a; 普通节点结构体结尾节点&#xff08;mini节点&#xff09;结构体链表结…...

【云原生•监控】基于Prometheus实现自定义指标弹性伸缩(HPA)

【云原生•监控】基于Prometheus实现自定义指标弹性伸缩(HPA) 什么是弹性伸缩 「Autoscaling即弹性伸缩&#xff0c;是Kubernetes中的一种非常核心的功能&#xff0c;它可以根据给定的指标&#xff08;例如 CPU 或内存&#xff09;自动缩放Pod副本&#xff0c;从而可以更好地管…...

Windows、 Linux 等操作系统的基本概念及其常见操作

Windows 和 Linux 是两种常见的操作系统&#xff0c;它们在计算机领域中广泛使用。下面我将为您介绍它们的基本概念以及一些常见的操作。 **Windows 操作系统&#xff1a;** 1. **基本概念&#xff1a;** Windows 是由微软公司开发的操作系统系列&#xff0c;旨在为个人计算机…...

【RabbitMQ】golang客户端教程5——使用topic交换器

topic交换器&#xff08;主题交换器&#xff09; 发送到topic交换器的消息不能具有随意的routing_key——它必须是单词列表&#xff0c;以点分隔。这些词可以是任何东西&#xff0c;但通常它们指定与消息相关的某些功能。一些有效的routing_key示例&#xff1a;“stock.usd.ny…...

SpringBoot对接OpenAI

SpringBoot对接OpenAI 随着人工智能技术的飞速发展&#xff0c;越来越多的开发者希望将智能功能集成到自己的应用中&#xff0c;以提升用户体验和应用的功能。OpenAI作为一家领先的人工智能公司&#xff0c;提供了许多先进的自然语言处理和语言生成模型&#xff0c;其中包括深…...

(C++)继承

目录 1.继承的概念及定义 1.1继承的概念 1.2继承定义 1.2.1定义格式 1.2.2继承方式和访问限定符 1.2.3继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 5.继承与友元 6.继承与静态成员 7.复杂的菱形继承及菱形虚拟…...

图像处理技巧形态学滤波之膨胀操作

1. 引言 欢迎回来&#xff0c;我的图像处理爱好者们&#xff01;今天&#xff0c;让我们继续研究图像处理领域中的形态学计算。在本篇中&#xff0c;我们将重点介绍腐蚀操作的反向效果膨胀操作。 闲话少说&#xff0c;我们直接开始吧&#xff01; 2. 膨胀操作原理 膨胀操作…...

机器学习基础之《特征工程(4)—特征降维》

一、什么是特征降维 降维是指在某些限定条件下&#xff0c;降低随机变量&#xff08;特征&#xff09;个数&#xff0c;得到一组“不相关”主变量的过程 1、降维 降低维度 ndarry 维数&#xff1a;嵌套的层数 0维&#xff1a;标量&#xff0c;具体的数0 1 2 3... …...

学生管理系统(Python版本)

class Student:def __init__(self, id, name, age):self.id idself.name nameself.age ageclass StudentManagementSystem:def __init__(self):self.students []def add_student(self, student):self.students.append(student)print("学生信息添加成功&#xff01;&qu…...

Linux下快速创建大文件的4种方法总结

1、使用 dd 命令创建大文件 dd 命令用于复制和转换文件&#xff0c;它最常见的用途是创建实时 Linux USB。dd 命令是实际写入硬盘&#xff0c;文件产生的速度取决于硬盘的读写速度&#xff0c;根据文件的大小&#xff0c;该命令将需要一些时间才能完成。 假设我们要创建一个名…...

用 Rufus 制作 Ubuntu 系统启动盘时,选择分区类型为MBR还是GPT?

当使用 Rufus 制作 Ubuntu 系统启动盘时&#xff0c;您可以根据您的需求选择分区类型&#xff0c;MBR&#xff08;Master Boot Record&#xff09;还是 GPT&#xff08;GUID Partition Table&#xff09;。 MBR 是传统的分区表格式&#xff0c;适用于大多数旧版本的操作系统和旧…...

Nodejs+vue+elementui汽车租赁管理系统_1ma2x

语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 前端nodejsvueelementui, 课题主要分为三大模块&#xff1a;即管理员模块、用户模块和普通管理员模块&#xff0c;主要功能包括&#…...

Prometheus入门

Prometheus(普罗米修斯) 是一种 新型监控告警工具,Kubernetes 的流行带动了 Prometheus 的应用。 全文参考自 prometheus 学习笔记(1)-mac 单机版环境搭建[1] Mac 上安装 Prometheus brew install prometheus 安装路径在 /usr/local/Cellar/prometheus/2.20.1, 配置文件在 /usr…...

RISC-V云测平台:Compiling The Fedora Linux Kernel Natively on RISC-V

注释&#xff1a;编译Fedora&#xff0c;HS-2 64核RISC-V服务器比Ryzen5700x快两倍&#xff01; --- 以下是blog 正文 --- # Compiling The Fedora Linux Kernel Natively on RISC-V ## Fedora RISC-V Support There is ongoing work to Fedora to support RISC-V hardwar…...

Vim学习(三)—— Git Repo Gerrit

Git、Gerrit、Repo三者的概念及使用 三者各自作用&#xff1a; git&#xff1a;版本管理库&#xff0c;在git库中没有中心服务器的概念&#xff0c;真正的分布式。 repo&#xff1a;repo就是多个git库的管理工具。如果是多个git库同时管理&#xff0c;可以使用repo。当然使用…...

论坛项目之用户部分

注册接口 实现思路 1.特殊字段检查&#xff08;比如性别没有给出需要给出默认值&#xff09; 2.对比检查两次输入的密码是否一致&#xff0c;不一致报错 3.利用UUID生成随机‘盐’值&#xff0c;并使用密码进行MD5加密后与‘盐’进行拼接&#xff0c;生成加密后的密码 4.创建U…...

golang内存对齐

为什么要内存对齐&#xff1f; CPU访问内存时&#xff0c;以CPU的位数为单位进行访问。 如果访问未对齐的内存&#xff0c;处理器需要做两次内存访问&#xff0c;对齐的内存的访问可能仅需要一次&#xff0c;利用内存对齐后提升读取速度。 golang结构体内存对齐规则 在代码编译…...

【CheatSheet】Python、R、Julia数据科学编程极简入门

《Python、R、Julia数据科学编程极简入门》PDF版&#xff0c;是我和小伙伴一起整理的备忘清单&#xff0c;帮助大家10分钟快速入门数据科学编程。 另外&#xff0c;最近 TIOBE 公布了 2023 年 8 月的编程语言排行榜。 Julia 在本月榜单中实现历史性突破&#xff0c;成功跻身 …...

【golang】怎样判断一个变量的类型?

怎样判断一个变量的类型&#xff1f; package mainimport "fmt"var container []string{"zero", "one", "two"} func main() {container : map[int]string{0: "zero", 1: "one", 2: "two"}fmt.Printf…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化

是不是受够了安装了oracle database之后sqlplus的简陋&#xff0c;无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话&#xff0c;配置.bahs_profile后也能解决上下翻页这些&#xff0c;但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可&#xff0c…...