1 package com.xxx.utils; 2 3 import com.google.common.primitives.Ints; 4 5 import java.util.*; 6 7 public class ArrayGroupUtils { 8 9 public static void main(String[] args) { 10 // int[] arr = {5, 6, 4, 8, 7, 1, 2, 3};//4 5 6 7 8 11 int[] arr = {1, 2, 5, 6, 6, 9, 10, 17, 18, 2, 8, 20}; 12 List<List<Integer>> lists = minGroup(arr, 30); 13 for (List<Integer> list : lists) { 14 System.out.println(list); 15 } 16 } 17 18 19 /** 20 * 最少分组法-将数组arr中的数字分组,要求各个分组中数字之和小于等于k,求最小分组数的情况,默认arr中每个数均小于k 21 * <p> 22 * 第一步:排序,将数组先折腾成有序的(升序)。 23 * <p> 24 * 第二步:从数组第一个开始计算和,超过K了,这些就分一组。然后开始计算下一组的和,最后直到数组的末尾。 25 * <p> 26 * 第三步:现在每一组i都有一个到K距离的D[i]。现在除去第一个分组外将所有其它分组的D[i]进行排序。 27 * 从第一个分组中最大的数开始扫描,将它放置到能够容纳这个数的,距离K的D[i]最小的其它分组中。这个过程我称为分裂。分裂完成后要重新排序。 28 * <p> 29 * 终止条件:如果第一个分组全部分裂完成了,则再这样分裂第二个分组。直到某个分组不能分裂为止。 30 * 31 * @param arr 32 * @param k 33 */ 34 public static List<List<Integer>> minGroup(int[] arr, int k) { 35 //获取升序的list 36 List<Integer> list = Ints.asList(arr); 37 Collections.sort(list); 38 39 //子list 40 List<List<Integer>> subList = new ArrayList<>();//-->List<Map<Integer,List> > 41 List<List<Integer>> resultList = new ArrayList<>();//返回结果 42 43 44 Integer temp = 0; 45 List<Integer> tempList = new ArrayList<>(); 46 47 48 for (Integer integer : list) { 49 50 if ((temp + integer) < k) { 51 tempList.add(integer); 52 temp += integer; 53 } else if ((temp + integer) > k) { 54 temp = integer; 55 subList.add(tempList); 56 tempList = new ArrayList<>(); 57 tempList.add(integer); 58 } else { 59 tempList.add(integer); 60 temp = 0; 61 subList.add(tempList); 62 tempList = new ArrayList<>(); 63 } 64 65 66 } 67 subList.add(tempList);//加上最后一个数 68 69 70 for (int m = 0; m < subList.size(); m++) { 71 division(subList, resultList, k, m); 72 } 73 74 //处理sublist中为0的元素 75 List<List<Integer>> handZeroEleList = handZeroEle(subList); 76 77 return handZeroEleList; 78 79 80 } 81 82 83 private static void division(List<List<Integer>> subList, List<List<Integer>> resultList, int k, int m) { 84 85 /*生成D[i]:List的map按D[i]升序(除了第一个分组)*/ 86 List<Map<Integer, List>> mapList = getSortedList(subList, k, m); 87 88 //遍历第一个分组下的所有元素 89 List<Integer> subList1 = subList.get(m); 90 Collections.reverse(subList1); 91 92 for (int n = 0; n < subList1.size(); n++) { 93 Integer integer = subList1.get(n); 94 for (int j = 0; j < mapList.size(); j++) { 95 Map<Integer, List> listMap = mapList.get(j); 96 Integer diTemp = getFirstKey(listMap); 97 List<Integer> listTemp = getFirstValue(listMap); 98 if (integer > diTemp) {//不能放进去,则比较下一个分组 99 continue; 100 } else {//正好能放进去,则重新进行排序-->继续循环 101 //往里加 102 listMap.remove(diTemp); 103 diTemp -= integer; 104 listTemp.add(integer); 105 listMap.put(diTemp, listTemp); 106 107 //往第一个分组里删除 108 //it.remove(); 109 // integer = 0; 110 subList1.set(n, 0); 111 112 sortByCustom(mapList); 113 break; 114 115 } 116 } 117 } 118 resultList.add(subList1); 119 120 } 121 122 123 /** 124 * 获取除去第一个分组外将所有其它分组按D[i]进行排序 125 * 126 * @param subList 127 * @param k 128 * @return 129 */ 130 private static List<Map<Integer, List>> getSortedList(List<List<Integer>> subList, int k, int m) { 131 List<Map<Integer, List>> mapList = new ArrayList<>(); 132 for (int i = m + 1; i < subList.size(); i++) { 133 Map<Integer, List> tempMap = new HashMap<>(); 134 tempMap.put(k - listSum(subList.get(i)), subList.get(i)); 135 mapList.add(tempMap); 136 } 137 sortByCustom(mapList); 138 return mapList; 139 } 140 141 142 /** 143 * 排序 144 * 145 * @param mapList 146 * @return 147 */ 148 private static void sortByCustom(List<Map<Integer, List>> mapList) { 149 Collections.sort(mapList, new Comparator<Map<Integer, List>>() { 150 @Override 151 public int compare(Map<Integer, List> o1, Map<Integer, List> o2) { 152 if (getFirstKey(o1) > getFirstKey(o2)) { 153 return 1; 154 } 155 if (getFirstKey(o1) == getFirstKey(o2)) { 156 return 0; 157 } 158 return -1; 159 } 160 }); 161 } 162 163 164 /** 165 * 求数组和 166 * 167 * @param arr 168 * @return 169 */ 170 public static int arraySum(int[] arr) { 171 int sum = 0; 172 for (int i : arr) { 173 sum += i; 174 } 175 return sum; 176 } 177 178 /** 179 * 求list<integer>和 180 * 181 * @param list 182 * @return 183 */ 184 public static Integer listSum(List<Integer> list) { 185 Integer sum = 0; 186 for (Integer integer : list) { 187 sum += integer; 188 } 189 return sum; 190 } 191 192 193 /** 194 * 获取map中第一个key值 195 * 196 * @param map 数据源 197 * @return 198 */ 199 private static Integer getFirstKey(Map<Integer, List> map) { 200 Integer obj = null; 201 for (Map.Entry<Integer, List> entry : map.entrySet()) { 202 obj = entry.getKey(); 203 if (obj != null) { 204 break; 205 } 206 } 207 return obj; 208 } 209 210 211 /** 212 * 获取map中第一个数据值 213 * 214 * @param map 数据源 215 * @return 216 */ 217 private static List getFirstValue(Map<Integer, List> map) { 218 List obj = null; 219 for (Map.Entry<Integer, List> entry : map.entrySet()) { 220 obj = entry.getValue(); 221 if (obj != null) { 222 break; 223 } 224 } 225 return obj; 226 } 227 228 229 /** 230 * 将[0, 6, 6, 5, 0, 0] 231 * [0, 0, 17, 10] 232 * [2, 1, 9, 18]中的0去除掉 233 * 234 * @param subList 235 */ 236 private static List<List<Integer>> handZeroEle(List<List<Integer>> subList) { 237 List<List<Integer>> resultList = new ArrayList<>(); 238 for (List<Integer> integers : subList) { 239 List<Integer> list = new ArrayList<>(); 240 for (Integer integer : integers) { 241 if (integer != 0) { 242 list.add(integer); 243 } 244 } 245 if (list.size() > 0) { 246 resultList.add(list); 247 } 248 249 } 250 return resultList; 251 } 252 253 }