`
xiang37
  • 浏览: 414718 次
  • 性别: 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()这个方法。

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

 

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

分享到:
评论

相关推荐

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

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

    c程序设计习题参考(谭浩强三版)习题参考解答

    10.4有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成前面m个数。 75 写一函数实现以上功能,在主函数中输入n个整数,并输出调整后的n个数。 75 10.5有一字符串,包含n个字符。写一个函数,将此字符串中从...

    数据结构(C++)有关练习题

    &lt;br&gt;2、 已知a[n]为整数数组,试写出实现下列运算的递归代码(C或C++代码均可):&lt;br&gt;要求: a. 求数组中的最大整数;&lt;br&gt; b. 求n个数的和;&lt;br&gt; c. 利用堆栈类,将本题a和b的代码改成非递归的方式。&lt;br&gt;实验报告...

    C语言程序设计标准教程

    printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i--,i++,-i--); } i 这个程序与例2.13相比只是把多个printf语句改一个printf 语句输出。但从结果可以看出是不同的。为什么结果会不同呢?就是因为printf函数对输出表中各...

    计算机二级公共基础知识

    数据的逻辑结构是对数据元素之间的逻辑关系的描述,它可以用一个数据元素的集合和定义在此集合中的若干关系来表示。数据的逻辑结构有两个要素:一是数据元素的集合,通常记为D;二是D上的关系,它反映了数据元素之间...

    最新JAVA编程题全集_50题及答案

    程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。 public class lianxi02 { public static void main(String[] args) { int count = 0; for(int i=...

    数据结构自测卷集及答案

    3. 向一个长度为n的向量的第i个元素(1≤i≤n+1)之前插入一个元素时,需向后移动 n-i+1 个元素。 4. 向一个长度为n的向量中删除第i个元素(1≤i≤n)时,需向前移动 n-i 个元素。 5. 在顺序表中访问任意一结点的时间...

    语言程序设计课后习题答案

    面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。 面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--...

    达内 coreJava 习题答案

    规律:一个数等于前两个数之和 //计算斐波那契数列(Fibonacci)的第n个值 public class Fibonacci{ public static void main(String args[]){ int n = Integer.parseInt(args[0]); int n1 = 1;//第一个数 int n2...

    正则表达式

    一个字符类和它所包含的任何一个字符都匹配,所以正则表达式 / [abc] / 和字母 "a" , "b" , "c" 中的任何一个 都匹配.另外还可以定义否定字符类,这些类匹配的是除那些包含在中括号之内的字符外的所有字符.定义否定...

    《数据结构 1800题》

    16.设m.n均为自然数,m可表示为一些不超过n的自然数之和,f(m,n)为这种表示方式的数目。例f(5,3)=5, 有 5种表示方式:3+2,3+1+1,2+2+1,2+1+1+1,1+1+1+1+1。 ①以下是该函数的程序段,请将未完成的部分填入,...

    通信系统专业课程设计.doc

    通信系统专业课程设计 1.... 均衡性 m序列在一个周期内"1"和"0"的个数基本相等。具体来说,m序列的一个周期中的"0" 的个数比"1"的个数少一个。 2. 游程分布 我们把伪随机序列中取值("0"或"1")相同的一

    伙伴系统(代码+文档)

    若存在2i+1的一个空闲分区,则把该空闲分区分为相等的连个分区,这两个分区称为一对伙伴,其中的一个分区用于分配,而把另一个加入分区大小为2i的空闲分区链表中。若大小为2i+1的空闲分区不存在,则需要查找大小为2i...

    计算机二级C语言考试题预测

    (13) 设一棵完全二叉树共有699个结点,则在该二叉树中的叶子结点数为(B) 注:利用公式n=n0+n1+n2、n0=n2+1和完全二叉数的特点可求出 A. 349 B. 350 C. 255 D. 351 (14) 结构化程序设计主要强调的是(B) A.程序的规模 ...

    -初中化学知识点回顾(化学基本概念和原理).doc

     (1)带正电荷的离子叫做阳离子(核电荷数>核外电子数);带负电荷的离子叫做阴离子(核电荷数核外电子数=。  (2)原子在化学反应中得失电子的数目即阴阳离子所带电荷数。例如钠原子在反应中失去最外层的一个...

    初中化学知识点回顾(化学基本概念和原理).doc

     (1)带正电荷的离子叫做阳离子(核电荷数>核外电子数);带负电荷的离子叫做阴离子(核电荷数核外电子数=。  (2)原子在化学反应中得失电子的数目即阴阳离子所带电荷数。例如钠原子在反应中失去最外层的一个...

    2009达内SQL学习笔记

    like 'M%':M开头的 like '_a%':第二个字符是a的 like '%a%'所有含a的 (“_”表示一个任意字符;“%”表示任意多个任意字符。) 单引号里面的内容,大小写敏感。单引号用来限定字符串, 如果将值与串类型的列...

    会计理论考试题

    A、Windows98桌面 B、A> C、Windows98资源管理器 D、C> 8.关于文件的含义,比较正确的说法应该是 ___A____ 。 A、记录在存储介质上的一组相关信息的集合 B、记录在磁盘上的一组相关信息的集合 C、记录在磁盘上的一...

    seq2seq_polynomial

    针对预测目标序列和实地真实目标序列之间的严格字符串相等性对模型进行评估。 该模型的精度为0.86 。 指示 分为训练和测试集: python data.py 训练模型: python train.py 在测试集上评估模型: python main.py ...

Global site tag (gtag.js) - Google Analytics