程序员面试100题之十五:数组分割

背包问题【01、完全(恰好or不超过)、多重】【尚未整理完】 变形问题:2N长度数组,分成俩N长度的,使其和差值最小。【程序员面试100题之十五:数组分割】 (写在前面)背包问题 总结的要点: (黄色字体标题的代码为三个问题最终用的模板) 1.一维(矩阵)的01背包为啥要逆序(保证更新f[j]时,f[ j - weight[i] ]是没有放入物品i时的数据即f[ i - 1 ][ j - weight[i] ],因为01背包每个物品至... 阅读详情
一、题目概述:有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。
假设数组A[1..2N]所有元素的和是SUM。模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合。显然:
S(k, 1) = {A[i] | 1<= i <= k}
S(k, k) = {A[1]+A[2]+…+A[k]}
S(k, i) = S(k-1, i) U {A[k] + x | x属于S(k-1, i-1) }
按照这个递推公式来计算,最后找出集合S(2N, N)中与SUM/2最接近的那个和,这便是答案。这个算法的时间复杂度是O(2^N).
因为这个过程中只关注和不大于SUM/2的那个子数组的和。所以集合中重复的和以及大于SUM/2的和都是没有意义的。把这些没有意义的和剔除掉,剩下的有意义的和的个数最多就是SUM/2个。所以,我们不需要记录S(2N,N)中都有哪些和,只需要从SUM/2到1遍历一次,逐个询问这个值是不是在S(2N,N)中出现,第一个出现的值就是答案。我们的程序不需要按照上述递推公式计算每个集合,只需要为每个集合设一个标志数组,标记SUM/2到1这个区间中的哪些值可以被计算出来。关键代码如下:
#include<iostream>
using namespace std;

//有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。
int arr[] = {0,1,5,7,8,9,6,3,11,20,17};
const int N=5;
const int SUM = 87;

// 模仿动态规划解0-1背包问题的策略
int solve1()
{
	int i , j , s;
	int dp[2*N+1][N+1][SUM/2+2];

	/*
	用dp(i,j,c)来表示从前i个元素中取j个、且这j个元素之和不超过c的最佳(大)方案,在这里i>=j,c<=S
	状态转移方程:   
	限第i个物品       不取  
	dp(i,j,c)=max{dp(i-1,j-1,c-a[i])+a[i],dp(i-1,j,c)}
	dp(2N,N,SUM/2+1)就是题目的解。
	*/
	//初始化
	memset(dp,0,sizeof(dp));

	for(i = 1 ; i <= 2*N ; ++i)
	{
		for(j = 1 ; j <= min(i,N) ; ++j)
		{
			for(s = SUM/2+1 ; s >= arr[i] ; --s)
			{
				dp[i][j][s] = max(dp[i-1][j-1][s-arr[i]]+arr[i] , dp[i-1][j][s]);
			}
		}
	}

	//因为这为最终答案 dp[2*N][N][SUM/2+1];
	i=2*N , j=N , s=SUM/2+1;
	while(i > 0)
	{
		if(dp[i][j][s] == dp[i-1][j-1][s-arr[i]]+arr[i])   //判定这个状态是由哪个状态推导出来的
		{
			cout<<arr[i]<<" ";    //取中arr[i]
			j--;
			s -= arr[i];
		}	
		i--;
	}
	cout<<endl;
	return dp[2*N][N][SUM/2+1];
}

int solve2()
{
	int i , j , s;
	int dp[N+1][SUM/2+2];     //取N+1件物品,总合不超过SUM/2+2,的最大值是多少 
	memset(dp,0,sizeof(dp));    //初始状态都为0

	for(i = 1 ; i <= 2*N ; ++i)
	{
		for(j = 1 ; j <= min(i,N) ; ++j)
		{
			for(s = SUM/2+1 ; s >= arr[i] ; --s)    //01背包从大到小,可以省空间,即最外层的空间
			{
				dp[j][s] = max(dp[j-1][s-arr[i]]+arr[i] , dp[j][s]); 
			}
		}
	}
	//要求最优解则 空间不能优化,
	return dp[N][SUM/2+1];
}

int solve3()
{
	int i , j , s;
	int isOK[N+1][SUM/2+2]; //isOK[i][v]表示是否可以找到i个数,使得它们之和等于v
	memset(isOK,0,sizeof(isOK));    //都不合法
	//注意初始化
	isOK[0][0] = 1; //可以,取0件物品,总合为0,是合法的

	for(i = 1 ; i <= 2*N ; ++i)
	{
		for( j = 1 ; j <= min(i,N) ; ++j)
		{
			for(s = SUM/2+1 ; s >= arr[i] ; --s) //从大到小,数组少了一维
			{
				if( isOK[j-1][s-arr[i]] )
					isOK[j][s] = 1;
			}
		}
	}
	for(s = SUM/2+1 ; s >= 0 ; --s)
	{
		if(isOK[N][s])
			return s;
	}

	//要求最优解则空间不能优化
	return 0;
}

int main(void)
{
	int s1 = solve1();
	int s2 = solve2();
	int s3 = solve3();
	cout<<"s1="<<s1<<endl;
	cout<<"s2="<<s2<<endl;
	cout<<"s3="<<s3<<endl;
	system("pause");
	return 0;
}
二、扩展问题:  交换两个数组元素使两个数组和的差最小
有两个数组a、b,大小都为n,数组元素的值任意整形数,无序;
要求:通过交换a、b数组中的元素,使[数组a元素的和]与[数组b元素的和]之间的差最小。

其实这个问题就是上面问题的变形,将a、b两个数组合并为一个数组,然后问题就转化为将2*n个元素数组分割为2个长度为n的数组,并使两个子数组的和最接近。
另外,特别注意:如果数组中有负数的话,上面的背包策略就不能使用了(因为第三重循环中的s是作为数组的下标的,不能出现负数的),需要将数组中的所有数组都加上最小的那个负数的绝对值,将数组中的元素全部都增加一定的范围,全部转化为正数,然后再使用上面的背包策略就可以解决了。

Python设计哲学:从import this到工业级工程实践 Python不仅是一门编程语言,更是一套以可读性、简洁性和开发者体验为核心的软件工程方法论。其设计原理植根于自然语言结构(如主谓宾语法映射)与计算思维原语的统一,技术价值体现在降低认知负荷、加速迭代周期、支撑全栈分层治理。在教育领域,它已成为培养计算思维的‘第二语言’;在工业界,被Google、YouTube等用于高并发胶水层与AI基础设施。本文结合CPython执行机制、GIL真实影响、虚拟环境规范等实战要点,解析如何将Python之禅(如‘扁平胜于嵌套’‘可读性很重要’)转化为稳定、可维护、易协作的工程 阅读详情

相关推荐

【管理科学】第三十五篇 企业经营中的管理科学01 权力、风险、运营、物流、人力资源、库存、合同、品牌、业绩、项目

编号类型领域子领域/内容问题问题的数学分析(电磁/信息论/数学物理/数学化学/界面科学/表面科学 + 几何/拓扑/代数/集合论/图论/数论/函数评估/数值估计/概率/统计/向量/张量/矩阵/矢量 + 其他)算法逐步推理思考的数学表达式及实现步骤及时序流程 参数列表及参数的数值范围及数值分析及常量/常数1管理科学问题运营管理生产计划如何分配有限资源生产多种产品以最大化利润?线性代数、凸优化、单纯形法;向量与矩阵目标函数 max c^T x,约束 Ax ≤ b, x ≥ 0。步骤:①标准化引入松弛变量;②构建初

weixin_49199313的博客 247

程序员面试100题之十三:数组分割

一、题目概述:有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。 假设数组A[1..2N]所有元素的和是SUM。模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合。显然: S(k, 1) = {A[i] | 1&lt;= i &lt;= k} S(k, k) = {A[1]+A[2]+…+A[k...

tempsitegoogle 474

Flutter UI代码生成实战:Cursor与MCP的企业级规范适配

本文探讨了在企业级Flutter项目中,如何通过配置Cursor Rules与定制Figma MCP工具,为AI代码生成设定严格的开发规范。该方法解决了AI生成代码与现有项目架构、命名约定及资源引用规范脱节的核心痛点,实现了从Figma设计稿到高质量、可维护Flutter UI代码的自动化流程,显著提升团队协作效率与代码一致性。

http9protocoller的博客 280

求一堆序列,给定k个序列,求平方和最小

#include &lt;iostream&gt;#include &lt;vector&gt; #include &lt;stdio.h&gt;using namespace std;const int maxn=20;vector&lt;int&gt; temp,ans;int a[maxn];int n,k,x;int maxsqu=0;void dfs(int index,int nowk...

QAQ的小耗子的博客 710

QT使用openssl实现RSA加解密

使用openssl生成公私钥,随后用QT对相应的信息进行RSA加解密

weixin_42098322的博客 3867

从Datasheet到可用的Verilog模块:手把手教你为N25Q128 SPI Flash写状态机驱动

本文详细介绍了如何从Datasheet到实现可用的Verilog模块,手把手教你为N25Q128 SPI Flash编写状态机驱动。文章涵盖SPI Flash的核心工作机制、数据手册解析方法、Verilog状态机设计实践以及调试与性能优化技巧,特别适合FPGA开发者和硬件设计工程师参考。

weixin_30596023的博客 176

把一个长度为n的数组分成k段,让每段和的最大值最小。

const int MAX_COUNT = 100; int state[MAX_COUNT][MAX_COUNT]; int a[MAX_COUNT]; int MinSum(int n,int m) { int i = 0, j = 0, k = 0, temp = 0, MaxInt; for (i = 1;i <=n;++i) { state[i]

Jilong Sun(@Uchicago) 1万+

LayaNative源码编译

修改好后的LayaNative2.0需要重新编译生成Android和iOS所需要的动态库文件。

末之 1359

数据分析(一):创建数组+数组切片+数组组合+创建矩阵+数组广播+numpy文件读写+统计分析

一.Numpy简介 Numpy是用于数据科学计算的基础,不但能够完成科学计算任务,还能被用作高效的多维数据容器。用于存储和处理大型矩阵。 Python提供了一个array模块,和list不同,它直接保存数值,但是由于Python的array模块不支持多维,也没有各种运算函数。 Numpy弥补了这一遗憾,Numpy提供了一种存储单一数据类型的多维数组-----ndarray 二.创建数组对象...

Gym987的博客 1351

Python气象数据处理实战:用PyCINRAD轻松绘制雷达PPI图像(附避坑指南)

本文详细介绍了如何使用Python库PyCINRAD处理中国CINRAD系列天气雷达的基数据,并绘制专业的PPI图像。内容涵盖从环境配置、数据读取、核心绘图到高级定制与批量处理的完整流程,并针对安装依赖、中文乱码、数据范围等常见问题提供了实用的避坑指南,帮助气象工作者高效完成雷达数据可视化。

dog123的博客 222

拼多多/Temu反爬参数逆向踩坑记:从浏览器调试到补环境完整复盘

本文详细解析了拼多多/Temu反爬参数`anti_content`的逆向工程实战,从浏览器调试到补环境完整复盘。通过JavaScript逆向技术,拆解关键函数定位、反混淆算法还原及补环境技术应用,帮助开发者突破电商平台复杂反爬系统,提升数据采集效率。

weixin_33978722的博客 913

numpy-分割数组

一、创建一个一维数组 数组中的数据类型,下面实例可以看出优先级规则是:string > float > int 二、numpy的基本属性 1.数组元素的数据类型 2.数组元素的个数 3.数组的维数,下图表示一维 4.数组的维度大小,以元组表示 5.数组的转置 三、创建数组的集中方式 1.使用array创建浮点类型数组 将浮点类型数组转换为整数类型 2.使用arange创建数组 3.使用linspace创建线...

qq_14815199的博客 3263

Spec-Kit实战:用‘规范驱动开发’重构一个老旧Node.js项目(避坑指南)

本文详细介绍了如何使用Spec-Kit工具通过‘规范驱动开发’(SDD)重构老旧Node.js项目。从逆向工程提取规范到增量改造策略,再到避免典型陷阱,提供了实战指南和避坑技巧,帮助开发者高效实现架构现代化,显著提升代码质量和维护效率。

weixin_42525582的博客 555

程序员面试100题之十五 数组分割

程序员面试100题之十五 数组分割

fguihbfg的博客 193

第4.4节:保护轴承与安全系统

飞轮储能系统的保护轴承是磁悬浮失效时的最后安全屏障,其设计需满足非干涉性、高可靠性和有限寿命承载原则。转子跌落过程包括自由下落、碰撞、进动和滑行减速等复杂非线性阶段,产生远超常规工况的冲击载荷。保护轴承需具备极限冲击容量、高温耐受性和抗卡死能力。系统采用多层级安全架构,结合故障诊断与健康管理,通过监测振动、电流等参数实现预测性维护。安全停机序列有序结合主动制动与被动摩擦制动,确保系统在极端工况下的安全。保护轴承类型多样,需根据系统规模与可靠性要求合理选择。

技术工作者 229

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

2026大厂大模型/Agent面试题

1题目不是很全,因为不都是笔者的面试,都是笔者各个渠道(牛客,脉脉,boss直聘)刷到的,然后随缘汇总,帮助自己复习,也帮助大家复习。

weixin_44151034的博客 1762

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

海量数据处理实战指南:分治、Bitmap、Bloom Filter、外排序等十大经典套路与面试真题全解

> 本文是 Learn-Algorithms 仓库中 [海量数据处理](https://link.gitcode.com/i/271f00a0525a440da0e6e0a2373de309) 笔记的完整展开。当数据量大到"时间上算不完、空间上装不下"时,本指南将带你掌握一套可复用的解题框架——先估算数据规模,再按"Hash 映射 + 分而治之"切小问题,用 hash_map / Trie 树 /

gitblog_00580的博客 1002

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Docker 部署 iptvnator:手把手搭建自己的 IPTV 媒体中心

家里有一台常开的旧电脑或 NAS,想把一份 IPTV 播放列表变成全家随时能打开的网页版媒体中心?iptvnator 是一个开源的 IPTV 播放器,支持 m3u/m3u8 播放列表、Xtream Codes 和 Stalker 门户,官方提供了 Docker 部署方案:一条命令把前端 PWA 和后端服务打进同一个容器,浏览器打开就能看。整个过程不需要你写任何配置,跟着下面走一遍即可。 ## 项

gitblog_00947的博客 712

社区论坛应用基于HarmonyOS API 24:imagePlaceholder 用一个字符串表示配图占位,空字符串则表示该帖子没有配图,通过简单的条件判断决定是否渲染图片区域

本文将深入剖析一个基于 HarmonyOS ArkTS 开发的健身打卡应用。该应用集成了月历热力图、打卡时间轴、挑战任务、健身排行四大核心模块,采用了 HarmonyOS 声明式 UI 开发范式,充分运用了 ArkTS 的状态管理、组件化构建、响应式数据绑定等特性。通过逐段解析源码,我们将深入理解 ArkTS 在实际业务场景中的架构设计、状态流转和 UI 渲染机制。应用的整体架构遵循"数据驱动视图"的设计理念:底层定义严谨的数据模型与接口契约,中层通过配置化中心管理静态资源,上层以主组件统筹状态与视图,各

2302_79499487的博客 208

【动态规划】将一个包含 m 个整数的数组分成 n 个数组,每个数组的和尽量接近

1 背景 ClickHouse集群缩容,为保证数据不丢失,计划将需要缩容的节点上的数据,迁移到其他节点上,保证迁移到每个机器上的数据量尽量均衡。数据的迁移已partition为单位,已知每个partition的数据量。 2 抽象 将一个包含m个整数的数组分成n个数组,每个数组的和尽量接近 3 思路 这个问题是典型的动态规划的问题,理论上是无法找到最优解的,但是本次只是为了解决实际生产中的问题,而不是要AC,所以我们只需要找到一个相对合理的算法,使得partition的分配相对均衡就好了。 输入:

Bingo 9057

算法题:数组划分为和最相近2个子数组

算法题:数组划分为和最相近2个子数组 将一个数组划分为2个子数组,要求子数组的和尽可能接近。 思路 将数组排序,并计算出整个数组和。 计算区间和。从最小元素开始计算一个连续区间的和,当和小于数组和一半时,区间右边界右移,当和大于数组和一半时,区间左边界右移。当区间和最接近数组和的一半时记录左右边界的位置和区间和。当区间和等于数组一半时,此时区间中的元素即为一个划分方案中的子数组,直接返...

BetterWorld的专栏 4716

array的分割

import numpy as np arr1 = np.arange(12).reshape(3, 4) print(arr1) arr2, arr3 = np.split(arr1, 2, axis=1) # 切分成两个部分,按水平方向 print() print(arr2) print() print(arr3) arr4, arr5, arr6 = np.split(arr1, 3, axis=0) # 切分成3个部分,按垂直方向 print(arr4) print(arr5) print(ar

wangxf666的博客 860

编程之美2.18——数组分割

问题: 1. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为两个子数组,子数组的元素个数不限,并使两个子数组之和最接近。 2. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组之和最接近。 1. 解法1: 由于对两个子数组和最接近的判断不太直观,我们需要对题目进行适当转化。我们知道当一个子数组之和最接近

林云zju的专栏 1万+

python numpy--数组的组合和分割

数组的组合主要有: 1.水平组合:np.hstack(arr1,arr2) 或 concatenate(arr1,arr2,axis=1) 2.垂直组合:np.vstack(arr1,arr2) 或 concatenate(arr1,arr2,axis=0) 3.深度组合:np.dstack(arr1,arr2) 4.列组合:np.column_stack(arr1,arr2) 5.行组合:np...

qq_43287650的博客 1万+

数据结构实验一,第37题:数组的分割

描述 已知由n(n≥2)个正整数构成的集合A={ak}(0≤k<n),将其划分为两个不相交的子集A1和A2,元素个数分别是n1和n2,A1和A2中元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。 输入 多组数据,每组数据两行。第一行为一个整数n,代表数组中有n个元素。第二行为数组中的n个元素(元素之间用空格分隔)。当n等于0时,输入结束。 ...

Cznwtl的博客 4884

818. 数组排序

818. 数组排序 给定一个长度为 n 的数组 a 以及两个整数 l 和 r,请你编写一个函数,void sort(int a[], int l, int r),将 a[l]∼a[r] 从小到大排序

一个字,学 481
上一篇: 【2012百度之星/初赛下】C:度度熊的礼物
下一篇: 大端模式和小端模式
hackbuteer1
博客等级 码龄15年 1万+粉丝 251原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值