数组分割

本文深入解析了如何利用栈数据结构优化2*n长度数组的分割过程,以实现分割后两部分之和最接近的目标。通过单向遍历算法,实现数组元素的有效分配与组合,确保分割结果的高效与精准。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组分割

个人信息:就读于燕大本科软件工程专业 目前大三;

本人博客:google搜索“cqs_2012”即可;

个人爱好:酷爱数据结构和算法,希望将来从事算法工作为人民作出自己的贡献;

编程语言:C++ ;

编程坏境:Windows 7 专业版 x64;

编程工具:vs2008;

制图工具:office 2010 powerpoint;

硬件信息:7G-3 笔记本;


真言

痛的领悟,痛是有领悟的,痛的时候收获更多。

题目

数组分割:有2*n长度的整形数组,将其对半分割,分割后的两个数组的和最接近。

方案

用工具栈单向遍历(思路源于栈对二叉树分支搜索的例子)

算法设计用C++代码表示如下

// 数组分割
	void Array::Divided_Array(int * data,const unsigned int length)
	{
	// 异常输入
		if(data == NULL || length == 0 || length %2 != 0)
		{
			cout<<"异常输入 Divided_Array"<<endl;
		}

	// 正常输入
		else
		{
		// 开辟空间,选择算法辅助工具
			stack<unsigned int> S ;
			int sum_stack = 0 ;
			int min;
			unsigned int now ;
			unsigned int * result = new unsigned int[length/2];

		// 求出数组的和
			int sum_array = Sum_Array(data,length) ;
			cout<<"sum_array = "<<sum_array<<endl;
		// 核心算法
			S.push(0) ;
			sum_stack = data[0] ;
			min = sum_array/2 - sum_stack;
			now = 0;
			while( true )
			{
			
			// 进栈原则
			// 和不够大
				if(sum_stack < sum_array/2)
				{

				// 元素个数不够
					if(S.size() < length/2)
					{
					// 栈顶没有走到数组尾部
						if(now < length-1)
						{
							now++;
							S.push(now);
							sum_stack += data[now];
						}

					// 栈顶已经走到数组尾部
						else{
							if(S.empty() == false)
							{
								now = S.top();
								sum_stack -= data[S.top()];
								S.pop();
								
							}
							else break;
						}
					}

				// 元素个数已经够了,
				// 检查是否比当前组合更符合大案要求,
				// 如果是则保存一下
					else if(S.size() == length/2)
					{
						if(sum_array/2 - sum_stack < min)
						{
							min = sum_array/2 - sum_stack;
							Stack_To_Array(S,result);
						}
					// 出栈,更新栈,继续寻找
						now = S.top();
						sum_stack -= data[now];
						S.pop();

					}
				}

			// 出栈原则
				else if(sum_stack > sum_array/2)
				{
				// 出栈,更新栈,继续寻找
					now = S.top();
					sum_stack -= data[now];
					S.pop();
					
				}

			// 如果当前栈的和等于数组和的一半
				else
				{
					if(S.size() == length/2)
					{
						min = sum_array/2-sum_stack;
						Stack_To_Array(S,result);
						break;
					}
					else 
					{
						// 出栈,更新栈,继续寻找
						if(S.empty() == false)
						{
							now = S.top();
							sum_stack -= data[S.top()];
							S.pop();						
						}
						else break;
					}
				}
			}

			cout<<"min = "<<min<<endl;
			cout<<"sum_stack = "<<sum_stack<<endl;
			cout<<"answer for 数组分割"<<endl;
			for(unsigned int i=0;i<length/2;i++)
			{
				cout<<data[result[i]]<<" ";
			}
			cout<<endl;
			
		}
	}

// 数组求和
	int Array::Sum_Array(int * data,const unsigned int length)
	{
	// 异常输入
		if(data == NULL || length == 0 || length %2 != 0)
		{
			cout<<"异常输入 Divided_Array"<<endl;
			return -1;
		}

	// 正常输入
		else
		{
			int sum = 0;
			for(unsigned int i =0;i<length;i++)
				sum += data[i];
			return sum;
		}
	}



// 栈复制到数组
	void Array::Stack_To_Array(stack<unsigned int> S,unsigned int * &data)
	{
		unsigned int length = S.size();
		if(length == 0)
		{
			return void(0);
		}
		data = new unsigned int[length];
		for(unsigned int i = length-1;i < length;i--)
		{
			data[i] = S.top();
			S.pop();
		}
		return void(0);
	}


实验

数组 int data[]={-9,0,-3,-5,-1,-2,6,80,56,23};

程序结果

这里只输出了一个分割后的数组 -9 0 -5 6 80 ,还有一个数组是 -3 -1 -2 56 23 


在 JavaScript 中,将一个数组分割为多个子数组是一项常见的数据处理操作。可以通过多种方式实现这一功能,包括使用 `slice()` 方法、`for` 循环结合 `push()` 方法等[^1]。 ### 使用 `slice()` 方法进行分块 `slice(start, end)` 方法可以提取数组中从 `start` 索引开始(包含)到 `end` 索引结束(不包含)的元素,并返回一个新的数组。通过循环控制每次切割的起始位置,可以将原数组按指定长度拆分为多个子数组: ```javascript function splitArrayIntoChunks(array, chunkSize) { const result = []; for (let i = 0; i < array.length; i += chunkSize) { result.push(array.slice(i, i + chunkSize)); } return result; } // 示例用法 const originalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const chunkedArray = splitArrayIntoChunks(originalArray, 4); console.log(chunkedArray); // [[1, 2, 3, 4], [5, 6, 7, 8], [9]] ``` 该方法利用了 `slice()` 的特性,在不影响原始数组的前提下生成新的子数组集合[^3]。 --- ### 使用 `reduce()` 实现简洁写法 除了传统的 `for` 循环结构外,还可以使用函数式编程的方法如 `reduce()` 来实现更简洁的代码逻辑: ```javascript function splitWithReduce(arr, size) { return arr.reduce((acc, _, index) => { if (index % size === 0) { acc.push(arr.slice(index, index + size)); } return acc; }, []); } // 示例调用 const nums = [1, 2, 3, 4, 5, 6, 7, 8]; const grouped = splitWithReduce(nums, 3); console.log(grouped); // [[1, 2, 3], [4, 5, 6], [7, 8]] ``` 此方法通过遍历数组并判断索引是否为块大小的倍数来决定是否创建新子数组,适用于需要链式表达或简化代码结构的场景[^2]。 --- ### 使用 `Array.from()` 构造器生成分组 另一种现代写法是使用 `Array.from()` 配合映射函数,根据目标子数组的数量构造出最终结果: ```javascript function chunkWithArrayFrom(array, size) { return Array.from({ length: Math.ceil(array.length / size) }, (_, i) => array.slice(i * size, (i + 1) * size) ); } // 示例调用 const data = [10, 20, 30, 40, 50, 60]; const chunks = chunkWithArrayFrom(data, 2); console.log(chunks); // [[10, 20], [30, 40], [50, 60]] ``` 这种方法利用了 `Array.from()` 可以根据类数组对象生成新数组的能力,并结合 `slice()` 完成分段逻辑[^3]。 --- ### 总结与适用场景 - **`slice()` + `for` 循环**:适合大多数基础场景,语法清晰直观。 - **`reduce()` 写法**:适合函数式编程风格项目,代码简洁但可读性略差。 - **`Array.from()` 方式**:适合需要基于计算长度动态生成子数组的情况。 选择合适的方式应根据具体需求,例如对性能的要求、代码可维护性以及开发者的习惯等因素综合考虑[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值