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

算法n个数按顺序分成m组,每组和尽量相近

 
阅读更多
package algorithm;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeMap;

/**
 * 
 * @Description: n个数按顺序分成m组,每组和尽量相近 
 * 思路:先递归求出所有切分点的组合方式,然后分别计算每组中的和,对每组和两两差值的绝对值累加,最小的为最优切分点。
 * 如:{1,2,3,4}分2组 可以{1}和{2,3,4} {1,2}和{3,4} {1,2,3}和{4}   不能为{1,3}{2,4} 
 * 缺点:当list很大,分的组很多的时候,效率很低,几十分钟才能算出来。
 * @author thrillerzw
 * @version 1.0
 * @create time 2014-4-28 下午6:47:19
 */
public class TestCombination {
	public static void main(String[] args) {
		List<Integer> lengthList = new ArrayList<Integer>();
		for(int i=0;i<6;i++){
			lengthList.add(new Random().nextInt(100));
		}
		long startTime=System.currentTimeMillis();
		int m = 3;
		List<List<Integer>> resultList = new ArrayList<List<Integer>>();
		if (lengthList.size() < m) {
			buildResultList(resultList, lengthList);
		} else {
			int endIndex = lengthList.size() - (m - 2);
			int[] tempArr = new int[m - 1];
			List<int[]> combList = new ArrayList<int[]>();
			int num = -1;
			//所有切分点的组合存入combList
			Combine(lengthList, m - 1, tempArr, 0, 0, combList);
			int[] resultArr = null;
			for (int[] combArr : combList) {
				for (int i = 0; i < combArr.length; i++) {
					System.out.print(combArr[i] + " ");
				}
				System.out.println();
				int[] sumArr = getSum(combArr, lengthList);
				int diffSum = computeDifferent(sumArr);
				if (diffSum < num || num == -1) {
					num = diffSum;
					System.out.println("num=" + num);
					resultArr = combArr;
				}
			}
			if (resultArr != null) {
				for (int result : resultArr) {
					System.out.print(result + " ");
				}
			}

			buildResultList(resultList, lengthList, resultArr);
		}
		long endTime=System.currentTimeMillis();
		long useTime=endTime-startTime;
		System.out.print(lengthList.size()+"个数分为"+m+"组使用毫秒时间"+useTime+" resultList=" + resultList);
	}
    //如果分组数m大于等于集合的长度。
	static void buildResultList(List<List<Integer>> resultList,
			List<Integer> dataList) {
		for (int i = 0; i < dataList.size(); i++) {
			List<Integer> list = new ArrayList<Integer>();
			list.add(dataList.get(i));
			resultList.add(list);
		}
	}

	// 根据最优切分点构建结果集
	static void buildResultList(List<List<Integer>> resultList,
			List<Integer> dataList, int[] resultArr) {
		if (resultList == null || dataList == null || resultArr == null) {
			return;
		}
		int j = 0;
		int maxJ = 0;
		for (int i = 0; i <= resultArr.length; i++) {
			if (i == resultArr.length) {
				maxJ = dataList.size();
			} else {
				maxJ = resultArr[i];
			}
			List<Integer> list = new ArrayList<Integer>();
			for (; j < maxJ; j++) {
				list.add(dataList.get(j));
			}
			resultList.add(list);
		}
	}
    //每种组合不同段的和。比如0--2  2--5   5--list的结尾
	static int[] getSum(int[] combArr, List<Integer> dataList) {
		if (combArr == null || dataList == null) {
			return null;
		}
		int[] sumArr = new int[combArr.length + 1];
		int j = 0;
		int sum = 0;
		int maxJ = 0;
		for (int i = 0; i <= combArr.length; i++) {

			if (i == combArr.length) {
				maxJ = dataList.size();
			} else {
				maxJ = combArr[i];
			}
			for (; j < maxJ; j++) {
				sum += dataList.get(j);
			}
			sumArr[i] = sum;
			System.out.println("sum=" + sum);
			sum = 0;
		}
		return sumArr;
	}

	// 数组中值两两比较,差的绝对值的和累加
	static int computeDifferent(int[] sumArr) {
		int diffSum = 0;
		for (int i = 0; i < sumArr.length; i++) {
			for (int j = i + 1; j < sumArr.length; j++) {
				diffSum += Math.abs(sumArr[i] - sumArr[j]);
			}
		}
		System.out.println("diffSum=" + diffSum);
		return diffSum;
	}

	// 所有切分点组合
	private static void Combine(List<Integer> lengthList, int num,
			int[] tempArr, int tempArrIndex, int low, List<int[]> combList) {
		if (lengthList == null || lengthList.size() < num) {
			return;
		}
		if (num == 0) {
			if (tempArr[tempArr.length - 1] != lengthList.size()) {
				combList.add(tempArr);
			}
		} else {
			for (int i = low; i < lengthList.size(); i++) {
				tempArr[tempArrIndex] = i + 1;
				Combine(lengthList, num - 1, tempArr, ++tempArrIndex, i + 1,
						combList);
				int[] newTempArr = new int[tempArr.length];
				System.arraycopy(tempArr, 0, newTempArr, 0, tempArr.length - 1);
				tempArr = newTempArr;
				tempArrIndex--;
			}
		}
	}

}

 

2、

package algorithm;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @Description: 按顺序累加,与平均值相差最小的分为一组。
 * 优点:解决数据、分组大时候,穷举所有组合效率低的问题。适合数据比较均匀的时候。
 * 缺点:大数集中分布到一头等特殊情况分组不好。
 * @author thrillerzw
 * @version 1.0
 * @create time 2014-4-30 上午9:52:16
 */
public class TestAverage {
	public static void main(String[] args) {
		List<Integer> lengthList = new ArrayList<Integer>();
		lengthList.add(1);
		lengthList.add(2);
		lengthList.add(8);
		lengthList.add(6);
		lengthList.add(4);
		lengthList.add(10);
	
		int m = 3;
		List<List<Integer>> resultList = new ArrayList<List<Integer>>();
		if (lengthList.size() < m) {
			buildResultList(resultList, lengthList);
		} else {
			int[] pointArr = findSplitPoint(lengthList, m);
			buildResultList(resultList, lengthList, pointArr);
		}
		System.out.print("resultList=" + resultList);
	}

	private static int[] findSplitPoint(List<Integer> lengthList, int m) {
		int totalNum = 0;
		for (int i = 0; i < lengthList.size(); i++) {
			totalNum += lengthList.get(i);
		}
		//平均值
		double average = (double) totalNum / (double) m;
		System.out.println("average=" + average);
		int groupNum = 0;
		int[] pointArr = new int[m - 1];
		int pointArrIndex = 0;
		double minDiffSum = -1;
		int i = 0;
		for (; i < lengthList.size(); i++) {
			int num = lengthList.get(i);
			//按顺序累加
			groupNum += num;
			double curDiffSum = Math.abs(groupNum - average);

			int surplusGroupNum = m - 1 - pointArrIndex;
			int surplusDataNum = lengthList.size() - i;
			int differNum = surplusDataNum - surplusGroupNum;
            
			if (differNum > 0) {
				//当前累加 与平均值的距离 < 上次累加与平均值的距离  
				if (curDiffSum < minDiffSum || minDiffSum == -1) {
					minDiffSum = curDiffSum;
				} else {
					//保存切分点
					pointArr[pointArrIndex] = i;
					if (pointArrIndex == m - 2) {
						break;
					}
					pointArrIndex++;
					groupNum = num;
					minDiffSum = Math.abs(num - average);
				}
			} else {
				//简单解决大数分布到头尾,不够分组的情况。把末尾的每个值单独分为一组。
				pointArr[pointArrIndex++] = i;
				int point = i + 1;
				for (int j = 0; j < surplusGroupNum - 1; j++) {
					pointArr[pointArrIndex++] = point++;
				}
				break;
			}

		}
		return pointArr;
	}

	static void buildResultList(List<List<Integer>> resultList, List<Integer> dataList) {
		for (int i = 0; i < dataList.size(); i++) {
			List<Integer> list = new ArrayList<Integer>();
			list.add(dataList.get(i));
			resultList.add(list);
		}
	}

	static void buildResultList(List<List<Integer>> resultList, List<Integer> dataList, int[] resultArr) {
		if (resultList == null || dataList == null || resultArr == null) {
			return;
		}
		int j = 0;
		int maxJ = 0;
		for (int i = 0; i <= resultArr.length; i++) {
			if (i == resultArr.length) {
				maxJ = dataList.size();
			} else {
				maxJ = resultArr[i];
			}
			List<Integer> list = new ArrayList<Integer>();
			for (; j < maxJ; j++) {
				list.add(dataList.get(j));
			}
			resultList.add(list);
		}
	}

}

 

0
0
分享到:
评论

相关推荐

    Minimal m Sums 给定n 个整数组成的序列,现在要求将序列分割为m 段,每段子序列中的数在原序列中连续排列。如何分割才能使这m段子序列的和的最大值达到最小?

    - 第一行包含两个整数 n 和 m,分别表示序列的长度和分割的段数。 - 第二行包含 n 个整数,表示序列中的元素。 **输出**: - 输出一行,包含一个整数,即 m 个子序列的和的最大值的最小可能值。 #### 示例 **输入...

    组合优化问题及算法PPT学习教案.pptx

    6. **车间作业调度问题**:n 个工件在 m 台机器上加工,每个工件有特定的工序顺序和时间,目标是最小化最后一个工件的完工时间。这种问题复杂度高,常用启发式和模拟退火算法来寻找接近最优的解。 7. **最大截问题...

    3种排序算法(快速、二路归并、插入)java

    在Java中,归并排序通常使用递归,每次将数组拆分为大小相近的两部分,直至每个部分只剩一个元素,然后逐个合并。二路归并排序的时间复杂度始终为O(n log n),无论输入数据的顺序如何,因此在处理大数据时更为稳定。...

    数据结构算法排序 效率比较

    归并排序也是一种分治算法,通过先将数组分成若干小数组,再合并这些小数组以得到最终结果。 - **比较次数**:归并排序的比较次数主要发生在归并过程中,每次归并操作都会对子数组中的元素进行比较。在最坏和最好...

    各种密度聚类算法.pdf

    聚类是一种无监督学习方法,旨在将数据集中的对象根据它们的相似性分成不同的组,即“类”。好的聚类算法应该具备以下特点:适应大规模数据、处理不同数据类型、发现多样聚类形态、降低专业知识需求、处理脏数据、对...

    数据结构试题

    在有向图和无向图对应的邻接表中,所含边结点分别有**e**个和**2e**个。这是因为在有向图中,每条边只出现在起点的邻接表中;而在无向图中,每条边会出现在两个顶点的邻接表中。 6. **AOV网定义** AOV网是一种**...

    weka学习报告91

    4. **HOMER(Hierarchical Optimal Multi-labelling with Equal-sized Representatives)**:HOMER采用层次化的结构来处理数据偏斜问题,通过均匀的k-means聚类将数据集分成大小相近的部分,然后在每个部分上训练多...

    大数据升序优化.pptx

    - **定义**: 将输入数据按顺序划分为多个较小的块,这些块分别在内存中进行排序,然后将排好序的块合并成一个有序的输出。 - **影响因素**: 效率受可用内存大小的影响。 - **优化方法**: 通过调整块的大小来优化...

    易语言分组插入排序.rar

    1. 将待排序的数组分成大小相等或相近的小组,每个小组内的元素进行插入排序。插入排序的基本操作包括比较和交换,对于每个元素,将其与前面已排序的元素进行比较,如果小于前面的元素,则向前移动前面的元素,直到...

    BspSceneMgr.rar_BspSceneMgr

    【标签】"bspscenemgr" 提示我们,这个项目专注于BSP树的场景管理,这意味着它可能包含了如何利用BSP树进行场景层次结构的组织,以及如何优化物体的渲染顺序,以减少渲染开销和提高效率。 在实际应用中,BSP树有...

    2023-2024华为OD热点题目

    - **背景**:在一个数据集中找出众数和中位数。 - **核心知识点**: - **排序算法**:快速排序等用于排序数组。 - **众数计算**:使用哈希表统计各数值出现次数。 - **中位数计算**:根据排序后的数组位置确定中...

    基于GPS轨迹的用户兴趣点及路径挖掘研究

    1. 端点划分:首先将用户的整个GPS轨迹划分为成组的线段集,每个线段集代表用户在特定时间段内的移动行为。 2. 聚类分析:利用聚类方法对地理上相近的端点进行聚类,以识别用户的固定活动点。聚类的目的是将地理上...

Global site tag (gtag.js) - Google Analytics