Python世界:力扣题解1712,将数组分成三个子数组的方案数,中等

Python世界:力扣题解1712:将数组分成三个子数组的方案数,中等

    • 任务背景
    • 思路分析
    • 代码实现
    • 测试套件
    • 本文小结

任务背景


问题来自力扣题目1712. Ways to Split Array Into Three Subarrays,大意如下:

A split of an integer array is good if:

  • The array is split into three non-empty contiguous subarrays - named left, mid, right respectively from left to right.
  • The sum of the elements in left is less than or equal to the sum of the elements in mid, and the sum of the elements in mid is less than or equal to the sum of the elements in right.

Given nums, an array of non-negative integers, return the number of good ways to split nums. As the number may be too large, return it modulo 10^9 + 7.

翻译下,需求是:对给定无序数组划分成三组子数组,划分后要求左、中、右数组元素和递增,返回可划分的方法总数,若不可划分,则返回-1.

思路分析


第一个坑,读题失误,不是元素个数和递增,而是元素之和要递增。下面为错误做法,埋坑警戒。

import mathclass Solution(object):def waysToSplit(self, nums):""":type nums: List[int]:rtype: int"""res = 0nums_len = len(nums)ways_total = 0left_max = nums_len // 3 + 1for l in range(1, left_max):mid_max = (nums_len - l) // 2 + 1for m in range(l, mid_max):r = nums_len - l - mif (l <= m) and (m <= r) and (l + m + r == nums_len):ways_total += 1res = ways_totalreturn res

搞清楚真正意图后,思路如下:

  • 先获取一个同样大小sum_arr数组,累加nums的元素和,构造有序数组,创造二分条件
  • 对sum_arr数组做两个划分,即插两个板子,先定左板依次向右遍历
  • 再浮动右板,找到第一个大于左板划分子数组mid,即找数组左上界low
  • 再移动右板,找到第一个超过右板划分子数组right,即找数组右上界high
  • 区间长度len=high-low,即为该定左板的可划分总数
  • 依次移动左板,重复此步骤,累加len得到总的split_ways

代码实现


在这里插入图片描述

# nums,升序;找到第一个大于target值的索引
def get_array_left_bound(nums, l, h, t):# range: [low, high)target = tlow = lhigh = hfound_flag = Falsewhile (low < high):mid = low + (high - low) // 2if (nums[mid] >= 2*target):high = midfound_flag = Trueelse:low = mid + 1if found_flag:return lowreturn -1# nums,升序;找到最后一个大于target值的索引
def get_array_right_bound(nums, l, h, t):# range: [low, high)tar = tlow = lhigh = h# range: [low, high)found_flag = Falsewhile (low < high):mid = low + (high - low) // 2acc = nums[mid] - nums[l]left = acc + tarright = nums[h - 1] - nums[mid]if (left > right): # 不满足预期,缩减右界high = midelse: # 若 left <= rightlow = mid + 1found_flag = Trueif low > h - 1:low = h - 1if found_flag:return low  # 返回low-1则表示right右界,能取到;返回low,则表示右界临界值,无法取。return -1def get_array_sum(nums):nums_len = len(nums)nums_sum = []val_sum = 0for i in range(nums_len):val_sum += nums[i]nums_sum.append(val_sum)# print(nums_sum)return nums_sumdef get_ways(nums, l):h = len(nums)t = nums[l] # left res, 0-lstart = get_array_left_bound(nums, l + 1, h, t)# start最大只能为倒数第二个索引,要确保最后至少有一个子数组if (start < 1 or start + 1 >= h):return 0t = nums[start] - nums[l] # mid res, [l+1, start]end = get_array_right_bound(nums, start, h, t)if (end <= start): # start最远能偏移的边界return 0ways = end - startreturn ways# sum + binary
class Solution(object):def waysToSplit(self, nums):""":type nums: List[int]:rtype: int"""res = 0nums_len = len(nums)nums_sum = get_array_sum(nums)# 左右边界挡板ways_total = 0left_max = nums_len - 1for l in range(0, left_max):if (2*nums_sum[l] > nums_sum[nums_len - 1]):breakways_total += get_ways(nums_sum, l)res = ways_total % 1_000_000_007return res

这里也埋了个坑,最开始94行没有注意处理大数取余10^9+7,导致[0, 0, 0, 0, 0, …]大数用例一直无法通过。

测试套件


单例测试demo:

# one case test
nums = [1,1,1]
nums = [1,2,2,2,5,0]
nums = [3,2,1]
nums = [0,0,0,0]
nums = [0, 0, 0, 0] # 3
nums = [0, 0, 0, 0, 0] # 6sol = Solution()
res = sol.waysToSplit(nums)
print(res)

套件测试demo:

# 导入单元测试
import unittestdef test_base(self, nums, ret):sol = Solution()res = sol.waysToSplit(nums)self.assertEqual(res, ret)# 编写测试套
class TestSol(unittest.TestCase):def test_special1(self):nums = [1,1,1]ret = 1test_base(self, nums, ret)def test_special2(self):nums = [0,0,0]ret = 1test_base(self, nums, ret)def test_special3(self):nums = [0,0,0,0]ret = 3test_base(self, nums, ret)def test_special4(self):nums = [0,0,0,0,0]ret = 6test_base(self, nums, ret)def test_common1(self):nums = [1,2,2,2,5,0]ret = 3test_base(self, nums, ret)def test_common2(self):nums = [3,2,1]ret = 0test_base(self, nums, ret)def test_common3(self):nums = [1,2,2,2,5,0]ret = 3test_base(self, nums, ret)# 含测试套版本主调
if __name__ == '__main__':print('start!')unittest.main() # 启动单元测试print('done!')

本文小结


此题关键点在于二分法左右边界的获取,需要对边界条件有很熟练的处理,同时注意题意处理和特殊用例,如全零大数组处理,可用排列组合Cm2公式来处理,获取理论值。

  1. 参考实现1:https://leetcode.com/problems/ways-to-split-array-into-three-subarrays/solutions/999157/python3-binary-search-2-pointer/
  2. 参考实现2:https://blog.csdn.net/weixin_59916649/article/details/125187567

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/60074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java集合框架之映射(Map)

引言 在Java编程中&#xff0c;管理键值对数据是一项常见的任务。Java集合框架中的Map接口为此提供了强大的支持。Map接口允许我们存储键值对&#xff0c;并提供了丰富的方法来操作这些键值对。本文将详细介绍Map接口的内部机制、特性、操作方法以及在实际编程中的应用场景。 …

Java集合基础——针对实习面试

目录 Java集合基础什么是Java集合&#xff1f;说说List,Set,Queue,Map的区别&#xff1f;说说List?说说Set?说说Map&#xff1f;说说Queue?为什么要用集合&#xff1f;如何选用集合&#xff1f; Java集合基础 什么是Java集合&#xff1f; Java集合&#xff08;Java Collect…

基于单片机的客车载客状况自动检测系统(论文+源码)

1系统整体设计 本课题为客车载客状况自动检测系统&#xff0c;在此以STM32单片机为核心控制器&#xff0c;结合压力传感器、红外传感器、蜂鸣器、语音提示模块、继电器、液晶等构成整个客车载客状况自动检测系统&#xff0c;整个系统架构如图2.1所示&#xff0c;在此通过两个红…

卷积核参数详细介绍

卷积核参数详细介绍如下&#xff1a; 2. 尺寸&#xff1a;卷积核通常是一个小矩阵&#xff0c;如3x3、5x5等&#xff0c;定义了卷积的大小范围&#xff0c;在网络中代表感受野的大小。 3. 权重&#xff1a;卷积核中的每个元素都有一个权重值&#xff0c;用于捕捉输入数据的特征…

第 3 章 -GO语言 基本语法

1. 注释 在编程中&#xff0c;注释是帮助理解代码的重要工具。Go语言支持两种类型的注释&#xff1a; 单行注释&#xff1a;以 // 开头&#xff0c;直到行尾都是注释。多行注释&#xff1a;以 /* 开始&#xff0c;以 */ 结束&#xff0c;可以跨越多行。 示例 package maini…

渗透测试(socket,namp,scapy)

socket:可以用来实现不同虚拟机或者不同计算机之间的通信。 socket常用函数&#xff1a; sock.bind(host,port) //host可接受client范围&#xff0c;以及连接的端口 sock.listen()//sever开启监听连接 sock.accpet()//返回 sock&#xff0c;addr 用来接受和发送数据 addr…

【mongodb】数据库的安装及连接初始化简明手册

NoSQL(NoSQL Not Only SQL )&#xff0c;意即"不仅仅是SQL"。 在现代的计算系统上每天网络上都会产生庞大的数据量。这些数据有很大一部分是由关系数据库管理系统&#xff08;RDBMS&#xff09;来处理。 通过应用实践证明&#xff0c;关系模型是非常适合于客户服务器…

内网对抗-信息收集篇SPN扫描DC定位角色区域定性服务探针安全防护凭据获取

知识点&#xff1a; 1、信息收集篇-网络架构-出网&角色&服务&成员 2、信息收集篇-安全防护-杀毒&防火墙&流量监控 3、信息收集篇-密码凭据-系统&工具&网站&网络域渗透的信息收集&#xff1a; 在攻防演练中&#xff0c;当完成边界突破后进入内…

OpenWebUI,RAG+外部知识库+AI写文的开源应用

引言 自从去年AI火起来之后&#xff0c;很多人便热衷于寻找适合自用的AI开源项目&#xff0c;把各家大模型API接入到自己的AI程序里&#xff0c;便可以通过AI辅助完成一系列日常任务&#xff0c;比如内容翻译/润色/总结/撰写、格式转换、数据分类、代码分析、角色扮演等等。 …

qt QErrorMessage详解

1、概述 QErrorMessage是Qt框架中用于显示错误消息的一个对话框类。它提供了一个简单的模态对话框&#xff0c;用于向用户显示错误或警告消息。QErrorMessage通常用于应用程序中&#xff0c;当需要向用户报告错误但不希望中断当前操作时。它提供了一个标准的错误消息界面&…

洛谷 P1622 释放囚犯(区间dp)

题目链接 https://www.luogu.com.cn/problem/P1622 思路 d p [ i ] [ j ] dp[i][j] dp[i][j]表示释放区间 [ i , j ] [i,j] [i,j]的罪犯所需的最小的肉&#xff0c;状态转移方程为&#xff1a; d p [ i ] [ j ] m i n ( d p [ i ] [ j ] , d p [ i ] [ k − 1 ] d p [ k 1…

一文了解Android的Doze模式

Android 的 Doze 模式是一项省电功能&#xff0c;主要用于减少设备的功耗&#xff0c;特别是在屏幕关闭且设备长时间未被使用的情况下。Doze 模式在 Android 6.0&#xff08;API Level 23&#xff09;首次引入&#xff0c;并在后续版本中不断改进&#xff0c;以便更智能地管理后…

美团代付微信小程序系统 read.php 任意文件读取漏洞复现

0x01 产品简介 美团代付微信小程序系统是美团点评旗下的一款基于微信小程序技术开发的应用程序功能之一,它允许用户方便快捷地请求他人为自己支付订单费用。随着移动支付的普及和微信小程序的广泛应用,美团作为中国领先的本地生活服务平台,推出了代付功能,以满足用户多样化…

SpringBoot-员工管理系统(1)

目录 一、首页配置 二、国际化 2.1 配置文件编写 2.2 使配置文件生效 2.3 配置页面国际化值 2.4 实现根据按钮自动切换中英文 三、登录拦截器 一、首页配置 1、所有页面的静态资源都需要用thymeleaf接管 2、url使用{}格式 二、国际化 2.1 配置文件编写 1、在resourc…

Git - 命令杂谈 - reset、revert和clean

记录一些平时常用的Git命令 reset # 操作HEAD的指向&#xff0c;修改当前分支仓库区提交树 git reset option commitID--soft&#xff0c;不碰索引区和工作区&#xff0c;只修改HEAD指向--mixed&#xff0c;不碰工作区&#xff0c;重置索引区&#xff0c;修改HEAD指向--hard&a…

JavaSE:初识Java(学习笔记)

java是高级语言的面向对象语言 .[最贴近生活.最快速分析和设计程序] 一&#xff0c;计算机语言发展历史 二&#xff0c;Java体系结构 1&#xff0c;JavaSE&#xff08;Java Standard Edition&#xff09; 标准版&#xff0c;定位在个人计算机上的应用 这个版本是Jav…

ThreadLocal 的概念及使用场景(登录状态验证)

一、ThreadLocal 的概念 ThreadLocal 是 Java 中用于解决多线程并发问题的类。它通过为每个线程提供单独的变量副本&#xff0c;使得每个线程都可以对这些变量进行独立的访问和修改&#xff0c;而不影响其他线程中的相同变量。 简单来说&#xff0c;ThreadLocal 为每个使用它…

Android——多线程、线程通信、handler机制

Android——多线程、线程通信、handler机制 模拟网络请求&#xff0c;会阻塞主线程 private String getStringForNet() {StringBuilder stringBuilder new StringBuilder();for (int i 0; i < 100; i) {stringBuilder.append("字符串" i);}try {Thread.sleep(…

Jumpserver

概述 一款开源的堡垒机&#xff0c;可使系统的管理员和开发人员安全的连接到企业内部服务器上执行操作&#xff0c;是一款非常安全的远程连接工具。 4A 身份验证授权控制账号管理安全审计 安装 [rootjumpserver project]# tar -xf jumpserver-offline-installer-v2.28.6-amd64…

鸿蒙ArkTS和TS有什么区别?

Ark是强类型&#xff0c;打包编译的时候会保留类型。提高程序运行效率。 TS 支持类型校验&#xff0c;但是并不严格&#xff0c;支持any、unknown 这些不明确的类型。编译后其实jsd.ts,js文件不保留类型。 ArkTS基本禁用了动态类型 比如对象不能随意添加或者删除某些属性&am…