`
xiang37
  • 浏览: 426752 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

将M个数分为N组(M>N),保证N组之间的数之和几乎相等

 
阅读更多

将M个数分为N组(M>N),保证N组之间的数之和几乎相等;

花了点时间,虽然很简单的一个命题。其实最多1个小时就可写完的事,由于粗心,花了3个小时才调完。

 

package com.xiva;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.junit.Test;

/**
 * @Description 假定needSortNum个数,分为groupsNum组
 * @author XGT
 *
 */
public class Subgroup {

	List<Integer> numList = new ArrayList<Integer>();
	
	List<Integer> cloneList = new ArrayList<Integer>();
	
	//平均数
	Long averageNum = 0l;
	
	//需要分组的个数
	static int needSortNum = 100000;
	
	//组数
	static int groupsNum = 213;
	
	//数据产生范围
	static int range = 10000000;
	
	//当前存储的组数
	int currGroup = 0;
	
	Map<Integer, List<Integer>> resultMap = new HashMap<Integer, List<Integer>>();
	
	
	/**
	 * 随即产生range以内的needSortNum个数字
	 */
	private void genarateNum(){
		for (int i=0; i<needSortNum; i++){
			Random ran     = new Random(System.nanoTime());
			int randNum    = ran.nextInt(range);
			Integer numObj = Integer.valueOf(randNum);
			numList.add(numObj);
		}
	}
	
	/**
	 * 进行从小到大的排序
	 */
	private void sortNum(){
		
		Object[] numArray =  numList.toArray();
		Arrays.sort(numArray);
		int length = numArray.length;
		for (int i=0; i<length; i++){
			numList.set(i, Integer.valueOf(numArray[i].toString()));
		}
		System.out.println("最大值:"+numList.get(numList.size()-1)+"最小值:"+numList.get(0));
	}
	
	/**
	 * 计算平均值
	 */
	private void setAverageNum(){
		long totalNum = 0l;
		int size = numList.size();
		for (int i=0; i<size; i++){
			totalNum = totalNum + numList.get(i);
		}
		averageNum = totalNum/groupsNum;
	}
	
	
	/**
	 * 开始分组
	 */
	private void start2Divide(){
		
		cloneList.addAll(numList);
		
		int size = numList.size();
		long groupTempNum = 0l;
		
		int currIndex = size-1;
		
		List<Integer> tempList = new ArrayList<Integer>();
		while(cloneList.size() > 0){
			groupTempNum = groupTempNum + cloneList.get(currIndex);
			if(groupTempNum < averageNum){
				tempList.add(cloneList.get(currIndex));
				cloneList.remove(currIndex);
				currIndex = currIndex -1;
			}else{
				long groupNum = groupTempNum - cloneList.get(currIndex);
				
				while(groupNum < averageNum){
					long difference2 = averageNum -  groupNum;
					int index2 = getSuitedIndex(difference2, cloneList);
					if (index2 == 0)
						break;
					Integer suitedObj2 = cloneList.get(index2);
					
					tempList.add(cloneList.get(index2));
					cloneList.remove(index2);
					currIndex = currIndex -1;
					
					groupNum = groupNum + suitedObj2;
				}
				
				storeList2Map(tempList);
				groupTempNum = 0;
			}
			
			if(currGroup == groupsNum-1){
				doTheRestNum();
				break;
			}
		}
	}
	
	
	/**
	 * @Description 返回与差值比较小的index
	 * @param difference
	 * @param cloneList
	 * @return
	 */
	private int getSuitedIndex(long difference, List<Integer> cloneList){
		int size = cloneList.size();
		int reIndex = 0;
		
		for (int i=0; i<size; i++){
			long currAbs = difference - cloneList.get(i);
			if ( currAbs > 0){
				continue;
			}else{
				reIndex = i;
				break;
			}
		}
		if (reIndex==0){
			System.out.println("这样就最小了~");
			reIndex = 0;
		}
		else{
			if (Math.abs(difference - cloneList.get(reIndex-1)) < Math.abs(difference - cloneList.get(reIndex)) )
			{
				reIndex = reIndex -1;
			}
		}
		return reIndex;
	}
	
	/**
	 * @Description 将分组的数据保存到Map
	 * @param tempList
	 */
	private void storeList2Map(List<Integer> tempList){
		List<Integer> gourpList = new ArrayList<Integer>();
		gourpList.addAll(tempList);
		currGroup = currGroup + 1;
		resultMap.put(Integer.valueOf(currGroup), gourpList);
		tempList.clear();
	}
	
    /**
     * 处理余下来的数据
     */
	private void doTheRestNum(){
		int size = cloneList.size();
		if ( size > 0){
			List<Integer> tempList = new ArrayList<Integer>();
			for (int i=0; i<size; i++){
				tempList.add(cloneList.get(i));
			}
			resultMap.put(Integer.valueOf(currGroup+1), tempList);
		}
	}
	
	private void printAllResult(){
		Set<Map.Entry<Integer, List<Integer>>> entrySet = resultMap.entrySet();
        Iterator<Map.Entry<Integer, List<Integer>>> iterator = entrySet.iterator();
        int total = 0;
        System.out.println("平均数:" + averageNum);
        while  (iterator.hasNext()) {  
            Map.Entry<Integer, List<Integer>> map = iterator.next();
            List<Integer> list = map.getValue();
            long totalNum = 0l;
            for(Integer obj:list){
            	totalNum = totalNum + obj;
//            	System.out.print(obj+";");
            }
            System.out.println();
            System.out.println("第"+map.getKey()+"组,"+"个数为:" + list.size()+",总值为:"+totalNum+"差值为:"+(totalNum-averageNum));
            total = total + list.size();
        }  
        System.out.println(total);
	}
	
	@Test public void testSorted(){
		
		genarateNum();
		sortNum();
		setAverageNum();
		start2Divide();
		printAllResult();
	}

}

 主要核心方法在于排序,取值的方法以及getSuitedIndex()这个方法。

这个是一个基本的解决方法,也可以基于这个程序之上,再写一个调优算法,保证最终结果正在趋于理想。

 

调优算法的思想是根据本组与平均值的差值去找其他组的元素相交换。

分享到:
评论

相关推荐

    基于Matlab解决m个人、n项任务的最优分派.pdf

    二元匹配问题是指在一组人和一组任务之间建立一个匹配关系,使得某项性能指标达到最优。根据匹配中人和任务的限制,可以分为多种情况,如每人最多只能完成一项任务,每项任务只能由一个人完成等。 在最优分派问题中...

    动态规划集合划分

    - 如果将第`n`个元素单独作为一个子集,则剩下的`n-1`个元素需要划分为`m-1`个非空子集,因此方法数为`f[n-1][m-1]`。 - 如果第`n`个元素不单独成为一个子集,那么它可以加入到前`n-1`个元素的任意一个子集中去。...

    M序列产生算法及构造伪随机数

    M序列的特性之一是其0和1的出现频率相等,即在一个周期内,逻辑1出现的次数与逻辑0出现的次数相同,均为\(2^{N-1}\)。在四级移位寄存器生成的M序列中,周期长度为15,这意味着在每个周期内,会有7次逻辑1和8次逻辑0...

    求两个等长有序序列的中位数_nonewqq_数据结构_

    在统计学中,中位数是一组数值中间的数,将这组数分为相等的两部分,一半的数比中位数小,另一半则比中位数大。对于两个等长的有序序列,我们可以直接取它们中间位置的数作为中位数,如果序列长度为奇数,则中位数是...

    用高斯消元法解线性方程组 的MATLAB程序

    - `function[RA,RB,n,X]=gaus(A,b)` 定义了函数`gaus`,输入参数为系数矩阵`A`和常数向量`b`,输出为系数矩阵的秩`RA`、增广矩阵的秩`RB`、方程组中的方程个数`n`以及解向量`X`。 - `B=[A b]` 构建增广矩阵`B`。 ...

    数据结构n阶魔方课程设计终极版2.doc

    数据结构n阶魔方课程设计涉及的是编程实现一种特殊的矩阵——魔幻方阵,它是一种填数游戏,要求1到n²的数字不重复地填入n×n的方阵中,使得每行、每列以及两条对角线上的数字之和都相等。这个课程设计主要针对3到15...

    整数拆分整数拆分整数拆分整数拆分整数拆分

    f(n, k) = f(n, k-1) + f(n-k, k),这表示 n 可以分为 k 个正整数的和,要么是 n 由前 k-1 个正整数组成,最后一个为 n-(k-1),要么是 n-k 由 k 个正整数组成,第一个为 k。 在给定的内容中,还提到了一些特定情况...

    Get清风Matlab求解非线性超定方程组-恰定方程组-欠定方程组.pdf

    2. **非线性恰定方程组**:当方程组的方程数量和未知数相等(n=m)时,称为恰定方程组。这类方程组通常有一个唯一的解。MATLAB提供`fsolve`函数也可以解决这类问题,但更直接的方法是使用`fminunc`或`lsqnonlin`,...

    2014届高考数学一轮复习 第10章《计数原理、概率、随机变量及其分布》(第1课时)知识过关检测 理 新人教A版.doc

    - 在100到999的所有三位数中,包含数字0的三位数的计数,需要考虑数字0的位置,分为个位、十位和个位十位都为0三种情况,分别计算后进行分类加法。 通过以上分析,我们可以看到这一章节复习内容涵盖了许多基础的...

    C语言编程经典100例

    找出100至999之间的所有水仙花数,水仙花数定义为一个三位数,其各位数字立方和等于该数本身。 #### 程序分析 - **数字分解**:通过整数除法和取余操作分解出百位、十位和个位上的数字。 - **立方和计算**:将各位...

    赠券收集问题1

    第二类斯特林数 S(n, m) 表示 n 个不同元素拆分为 m 个非空集合的方案数,其递推公式为 S(n + 1, m) = S(n, m − 1) + m ∙ S(n, m),而通项公式为 S(n, m) = 1/m! * (-1)^(n-m) * C(n-1, m-1)。 通过对这些问题的...

    学习C语言示例

    2. **计算方法:** 对于每一个三位数,分解出它的个位、十位和百位数字,然后计算这三个数字的立方和,如果与原数相等,则为水仙花数。 **程序源代码详解:** ```c main() { int i, j, k, n; printf("'...

    第十三章计数原理.doc

    5. 组合与组合数:组合是从n个不同元素中取出m个元素组成一组,但不考虑顺序。组合数的公式为C(n,m)=n!/m!(n-m)!。组合数有其特定的性质,如C(n, m) = C(n, n-m)等。 6. 组合问题的应用通常涉及“含”与“不含”的...

    2017_2018学年七年级数学下册第八章二元一次方程组8.2消元_解二元一次方程组一课一练基础闯关2含解析新版新人教版2018

    第2、3题则是将解代入方程组,通过运算找出m-n和m+3n的值。第4题考察了二元一次方程的定义,要求m+n的值,通过比较未知数的次数来确定条件。 此外,"鸡兔同笼"问题是一个经典的实例,它可以用二元一次方程组来解决...

    2017-2018_1《计算思维导论实验》考试.pdf

    4. 数字和的计算:给定一个正整数m,求其各位数字之和,涉及数字遍历和加法操作。 5. 完数判断:判断一个大于1的数m是否为完数,即其所有真因子(除了自身外的因数)之和等于m。需要进行因子检测和求和运算。 6. ...

    2018年九年级物理上册第十一章二滑轮第2课时滑轮组练习含解析新版苏科版

    例如,一个由一个定滑轮和一个动滑轮组成的滑轮组,可以将施力方向改变,并且可以将所需力减半。 知识点2:滑轮组改变力的方向和承担物重的绳子数量 如图所示,甲和乙滑轮组各有不同特点。甲滑轮组能改变动力方向,...

    基于决策树的n则交叉验证分类器

    在n折交叉验证中,原始数据集被分为n个相等大小的子集(或“折”)。分类器的训练和验证过程会重复n次,每次用其中n-1个子集的数据进行训练,剩下的一个子集用于测试。最后,将n次测试结果综合起来得到模型的平均...

    上海电机学院C语言实训答案

    一开始任选一个正整数m作为报数上限值,从第一个人开始按顺时针报数,报到m时停止,报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。...

    数论模板精心整编

    这个公式表达的是第 n 项 Fibonacci 数的平方加上第 n+1 项 Fibonacci 数的平方等于第 n+2 项 Fibonacci 数乘以第 n+3 项 Fibonacci 数减去 1 的差。数学上表示为: \[F_n^2 + F_{n+1}^2 = F_{n+2} \times F_{n+3} ...

Global site tag (gtag.js) - Google Analytics