C# 如何将一个数组分成3个部分,每个部分的总和大致相等
我有一个排列好的数组,我想把它分成3部分,这样它们的和就彼此最接近了 Ex: I have this array: 10, 8, 8, 7, 6, 6, 6, 5 so it'll be divided into 3 part like: p1 {10,8} sum = 18 p2 {8,7,6} sum = 21 p3 {6,6,5} sum = 17 我有这个阵列: 10, 8, 8, 7, 6, 6, 6, 5 因此,它将分为3部分,如: p1{10,8}和=18 p2{8,7,6}和=21 p3{6,6,5}和=17 更新代码: 我建议的方法如下(代码如下):C# 如何将一个数组分成3个部分,每个部分的总和大致相等,c#,algorithm,C#,Algorithm,我有一个排列好的数组,我想把它分成3部分,这样它们的和就彼此最接近了 Ex: I have this array: 10, 8, 8, 7, 6, 6, 6, 5 so it'll be divided into 3 part like: p1 {10,8} sum = 18 p2 {8,7,6} sum = 21 p3 {6,6,5} sum = 17 我有这个阵列: 10, 8, 8, 7, 6, 6, 6, 5 因此,它将分为3部分,如: p1{10,
- 创建数据结构(集合等)以表示所需的输出部分的数量(在示例3中)
- 按降序对输入数组排序
- 迭代输入数组的元素,并针对每个值:
- 选择一个输出部分以将值放入其中(这应该是当前总体总和最低的输出部分…)
- 将值添加到选定的输出零件
//输入数组
int[]inputArray=新的int[]{10,8,8,7,6,6,6,5};
//您想要的零件数量
int numberOfOutputParts=3;
//创建零件结构
List listOfParts=新列表();
对于(int i=0;i
上面使用的Part类的代码(尽管您可以使用更好的代码,如下所示):
公共类部分
{
公共列表值
{
得到;
设置
}
公共整数和
{
得到;
设置
}
///
///默认构造函数
///
公共部分()
{
值=新列表();
}
公共void AddValue(int值)
{
增加(价值);
CurrentSum+=值;
}
}
原始海报已经有了一个有效的解决方案(注释中有说明),可以将阵列分成两个等额的部分;称之为split2
。可以使用split2
构建三部分版本
split2
将阵列拆分为两部分李>
split2
将另一部分拆分为两部分李>
这就像是NP难的问题,但不是很强的意义上的问题,你们可以有一个O(nK)算法,其中K是你们的输入和的大小,请看,也请看我的答案,但在你们的情况下,你们应该增加另一个维度来处理它 你能试试我的样品吗,这可能对你有帮助 我的算法: 1/根据输出数组的数目计算数组数的平均值(exp:value=3) 2/对阵列数求和,直到和与平均值(以1/计算)相比具有最小间隙 3/执行步骤2,直到到达数组编号的末尾 我使用C#3.5进行测试
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace WindowsFormsApplication2
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
ArrayList inputValue = new ArrayList();
int avgValue = 0;
bool isFinish = false;
private void button1_Click(object sender, EventArgs e)
{
#region Init data
isFinish = false;
avgValue = 0;
inputValue.Clear();
listBox1.Items.Clear();
//assum you input valid number without space and in desc sorting order
string[] arrNumber = textBox1.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int numberOfBreak = 3;
int record = Convert.ToInt32(arrNumber[0]);//update the record with the maximum value of the array numbers
for (int i = 0; i < arrNumber.Length; i++)
{
inputValue.Add(Convert.ToInt32(arrNumber[i]));
}
foreach (object obj in inputValue)
{
avgValue += (int)obj;
}
avgValue = avgValue / numberOfBreak;
#endregion
int lastIndex = 0;
while (!isFinish)
{
int index = GetIndex(lastIndex);
string sResult = "";
for (int i = lastIndex; i <= index; i++)
{
sResult += inputValue[i].ToString() + "-";
}
listBox1.Items.Add(sResult);
if (index + 1 < inputValue.Count)
{
lastIndex = index + 1;
}
sResult = "";
}
}
private int GetIndex(int startIndex)
{
int index = -1;
int gap1 = Math.Abs(avgValue - (int)inputValue[startIndex]);
int tempSum = (int)inputValue[startIndex];
if (startIndex < inputValue.Count - 1)
{
int gap2 = 0;
while (gap1 > gap2 && !isFinish)
{
for (int i = startIndex + 1; i < inputValue.Count; i++)
{
tempSum += (int)inputValue[i];
gap2 = Math.Abs(avgValue - tempSum);
if (gap2 <= gap1)
{
gap1 = gap2;
gap2 = 0;
index = i;
if (startIndex <= inputValue.Count - 1)
{
startIndex += 1;
}
else
{
isFinish = true;
}
if (startIndex == inputValue.Count - 1)
{
index = startIndex;
isFinish = true;
}
break;
}
else
{
index = i - 1;
break;
}
}
}
}
else if (startIndex == inputValue.Count - 1)
{
index = startIndex;
isFinish = true;
}
else
{
isFinish = true;
}
return index;
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用系统集合;
命名空间Windows窗体应用程序2
{
公共部分类表单2:表单
{
公共表格2()
{
初始化组件();
}
ArrayList inputValue=新的ArrayList();
int avgValue=0;
bool isFinish=false;
私有无效按钮1\u单击(对象发送者,事件参数e)
{
#区域初始化数据
isFinish=false;
平均值=0;
inputValue.Clear();
listBox1.Items.Clear();
//假设您输入的有效数字不带空格且按desc排序顺序
string[]arrNumber=textBox1.Text.Split(新字符[]{',},StringSplitOptions.RemoveEmptyEntries);
int numberOfBreak=3;
int record=Convert.ToInt32(arrNumber[0]);//使用数组号的最大值更新记录
for(int i=0;i
int total = 0, partSum = 0, partIndex = 0;
int noOfParts = 3; //Initialize the no. of parts
int[] input = { 10, 8, 8, 7, 6, 6, 6, 5 };
int[] result = new int[noOfParts]; //Initialize result array with no. of locations equal to no. of parts, to store partSums
foreach (int i in input) //Calculate the total of input array values
{
total += i;
}
int threshold = (total / noOfParts) - (total / input.Length) / 2; //Calculate a minimum threshold value for partSum
for (int j = input.Length - 1; j > -1; j--)
{
partSum += input[j]; //Add array values to partSum incrementally
if (partSum >= threshold) //If partSum reaches the threshold value, add it to result[] and reset partSum
{
result[partIndex] = partSum;
partIndex += 1;
partSum = 0;
continue;
}
}
if (partIndex < noOfParts) //If no. of parts in result[] is less than the no. of parts required, add the remaining partSum value
{
result[partIndex] = partSum;
}
Array.Reverse(result);
foreach (int k in result)
{
Console.WriteLine(k);
}
Console.Read();
int-total=0,partSum=0,partIndex=0;
int noOfParts=3;//初始化零件号
int[]输入={10,8,8,7,6,6,6,5};
int[]result=new int[noOfParts];//初始化结果数组,使位置数等于部件数,以存储pa
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace WindowsFormsApplication2
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
ArrayList inputValue = new ArrayList();
int avgValue = 0;
bool isFinish = false;
private void button1_Click(object sender, EventArgs e)
{
#region Init data
isFinish = false;
avgValue = 0;
inputValue.Clear();
listBox1.Items.Clear();
//assum you input valid number without space and in desc sorting order
string[] arrNumber = textBox1.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int numberOfBreak = 3;
int record = Convert.ToInt32(arrNumber[0]);//update the record with the maximum value of the array numbers
for (int i = 0; i < arrNumber.Length; i++)
{
inputValue.Add(Convert.ToInt32(arrNumber[i]));
}
foreach (object obj in inputValue)
{
avgValue += (int)obj;
}
avgValue = avgValue / numberOfBreak;
#endregion
int lastIndex = 0;
while (!isFinish)
{
int index = GetIndex(lastIndex);
string sResult = "";
for (int i = lastIndex; i <= index; i++)
{
sResult += inputValue[i].ToString() + "-";
}
listBox1.Items.Add(sResult);
if (index + 1 < inputValue.Count)
{
lastIndex = index + 1;
}
sResult = "";
}
}
private int GetIndex(int startIndex)
{
int index = -1;
int gap1 = Math.Abs(avgValue - (int)inputValue[startIndex]);
int tempSum = (int)inputValue[startIndex];
if (startIndex < inputValue.Count - 1)
{
int gap2 = 0;
while (gap1 > gap2 && !isFinish)
{
for (int i = startIndex + 1; i < inputValue.Count; i++)
{
tempSum += (int)inputValue[i];
gap2 = Math.Abs(avgValue - tempSum);
if (gap2 <= gap1)
{
gap1 = gap2;
gap2 = 0;
index = i;
if (startIndex <= inputValue.Count - 1)
{
startIndex += 1;
}
else
{
isFinish = true;
}
if (startIndex == inputValue.Count - 1)
{
index = startIndex;
isFinish = true;
}
break;
}
else
{
index = i - 1;
break;
}
}
}
}
else if (startIndex == inputValue.Count - 1)
{
index = startIndex;
isFinish = true;
}
else
{
isFinish = true;
}
return index;
}
}
}
int total = 0, partSum = 0, partIndex = 0;
int noOfParts = 3; //Initialize the no. of parts
int[] input = { 10, 8, 8, 7, 6, 6, 6, 5 };
int[] result = new int[noOfParts]; //Initialize result array with no. of locations equal to no. of parts, to store partSums
foreach (int i in input) //Calculate the total of input array values
{
total += i;
}
int threshold = (total / noOfParts) - (total / input.Length) / 2; //Calculate a minimum threshold value for partSum
for (int j = input.Length - 1; j > -1; j--)
{
partSum += input[j]; //Add array values to partSum incrementally
if (partSum >= threshold) //If partSum reaches the threshold value, add it to result[] and reset partSum
{
result[partIndex] = partSum;
partIndex += 1;
partSum = 0;
continue;
}
}
if (partIndex < noOfParts) //If no. of parts in result[] is less than the no. of parts required, add the remaining partSum value
{
result[partIndex] = partSum;
}
Array.Reverse(result);
foreach (int k in result)
{
Console.WriteLine(k);
}
Console.Read();
// calculate total
total = 0;
for(i = 0; i != size; ++i) {
total += array[i];
}
// partition
n_partitions = 3;
current_partition = 1;
subtotal = array[0];
for(i = 1; i != size; ++i) {
if(subtotal + array[i] > total / n_partitions) {
// start new partition;
current_partition++;
subtotal = array[i];
} else {
// push to current partition
subtotal += array[i];
}
}