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); } } }
相关推荐
- 第一行包含两个整数 n 和 m,分别表示序列的长度和分割的段数。 - 第二行包含 n 个整数,表示序列中的元素。 **输出**: - 输出一行,包含一个整数,即 m 个子序列的和的最大值的最小可能值。 #### 示例 **输入...
6. **车间作业调度问题**:n 个工件在 m 台机器上加工,每个工件有特定的工序顺序和时间,目标是最小化最后一个工件的完工时间。这种问题复杂度高,常用启发式和模拟退火算法来寻找接近最优的解。 7. **最大截问题...
在Java中,归并排序通常使用递归,每次将数组拆分为大小相近的两部分,直至每个部分只剩一个元素,然后逐个合并。二路归并排序的时间复杂度始终为O(n log n),无论输入数据的顺序如何,因此在处理大数据时更为稳定。...
归并排序也是一种分治算法,通过先将数组分成若干小数组,再合并这些小数组以得到最终结果。 - **比较次数**:归并排序的比较次数主要发生在归并过程中,每次归并操作都会对子数组中的元素进行比较。在最坏和最好...
聚类是一种无监督学习方法,旨在将数据集中的对象根据它们的相似性分成不同的组,即“类”。好的聚类算法应该具备以下特点:适应大规模数据、处理不同数据类型、发现多样聚类形态、降低专业知识需求、处理脏数据、对...
在有向图和无向图对应的邻接表中,所含边结点分别有**e**个和**2e**个。这是因为在有向图中,每条边只出现在起点的邻接表中;而在无向图中,每条边会出现在两个顶点的邻接表中。 6. **AOV网定义** AOV网是一种**...
4. **HOMER(Hierarchical Optimal Multi-labelling with Equal-sized Representatives)**:HOMER采用层次化的结构来处理数据偏斜问题,通过均匀的k-means聚类将数据集分成大小相近的部分,然后在每个部分上训练多...
- **定义**: 将输入数据按顺序划分为多个较小的块,这些块分别在内存中进行排序,然后将排好序的块合并成一个有序的输出。 - **影响因素**: 效率受可用内存大小的影响。 - **优化方法**: 通过调整块的大小来优化...
1. 将待排序的数组分成大小相等或相近的小组,每个小组内的元素进行插入排序。插入排序的基本操作包括比较和交换,对于每个元素,将其与前面已排序的元素进行比较,如果小于前面的元素,则向前移动前面的元素,直到...
【标签】"bspscenemgr" 提示我们,这个项目专注于BSP树的场景管理,这意味着它可能包含了如何利用BSP树进行场景层次结构的组织,以及如何优化物体的渲染顺序,以减少渲染开销和提高效率。 在实际应用中,BSP树有...
- **背景**:在一个数据集中找出众数和中位数。 - **核心知识点**: - **排序算法**:快速排序等用于排序数组。 - **众数计算**:使用哈希表统计各数值出现次数。 - **中位数计算**:根据排序后的数组位置确定中...
1. 端点划分:首先将用户的整个GPS轨迹划分为成组的线段集,每个线段集代表用户在特定时间段内的移动行为。 2. 聚类分析:利用聚类方法对地理上相近的端点进行聚类,以识别用户的固定活动点。聚类的目的是将地理上...