1 packagecom.xxx.utils;2
3 importcom.google.common.primitives.Ints;4
5 import java.util.*;6
7 public classArrayGroupUtils {8
9 public static voidmain(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> lists = minGroup(arr, 30);13 for (Listlist : lists) {14 System.out.println(list);15 }16 }17
18
19 /**
20 * 最少分组法-将数组arr中的数字分组,要求各个分组中数字之和小于等于k,求最小分组数的情况,默认arr中每个数均小于k21 *
22 * 第一步:排序,将数组先折腾成有序的(升序)。23 *
24 * 第二步:从数组第一个开始计算和,超过K了,这些就分一组。然后开始计算下一组的和,最后直到数组的末尾。25 *
26 * 第三步:现在每一组i都有一个到K距离的D[i]。现在除去第一个分组外将所有其它分组的D[i]进行排序。27 * 从第一个分组中最大的数开始扫描,将它放置到能够容纳这个数的,距离K的D[i]最小的其它分组中。这个过程我称为分裂。分裂完成后要重新排序。28 *
29 * 终止条件:如果第一个分组全部分裂完成了,则再这样分裂第二个分组。直到某个分组不能分裂为止。30 *31 *@paramarr32 *@paramk33 */
34 public static List> minGroup(int[] arr, intk) {35 //获取升序的list
36 List list =Ints.asList(arr);37 Collections.sort(list);38
39 //子list
40 List> subList = new ArrayList<>();//-->List >
41 List> resultList = new ArrayList<>();//返回结果
42
43
44 Integer temp = 0;45 List tempList = new ArrayList<>();46
47
48 for(Integer integer : list) {49
50 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> handZeroEleList =handZeroEle(subList);76
77 returnhandZeroEleList;78
79
80 }81
82
83 private static void division(List> subList, List> resultList, int k, intm) {84
85 /*生成D[i]:List的map按D[i]升序(除了第一个分组)*/
86 List> mapList =getSortedList(subList, k, m);87
88 //遍历第一个分组下的所有元素
89 List 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 listMap =mapList.get(j);96 Integer diTemp =getFirstKey(listMap);97 List 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 *@paramsubList127 *@paramk128 *@return
129 */
130 private static List> getSortedList(List> subList, int k, intm) {131 List> mapList = new ArrayList<>();132 for (int i = m + 1; i < subList.size(); i++) {133 Map tempMap = new HashMap<>();134 tempMap.put(k -listSum(subList.get(i)), subList.get(i));135 mapList.add(tempMap);136 }137 sortByCustom(mapList);138 returnmapList;139 }140
141
142 /**
143 * 排序144 *145 *@parammapList146 *@return
147 */
148 private static void sortByCustom(List>mapList) {149 Collections.sort(mapList, new Comparator>() {150 @Override151 public int compare(Map o1, Mapo2) {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 *@paramarr168 *@return
169 */
170 public static int arraySum(int[] arr) {171 int sum = 0;172 for (inti : arr) {173 sum +=i;174 }175 returnsum;176 }177
178 /**
179 * 求list和180 *181 *@paramlist182 *@return
183 */
184 public static Integer listSum(Listlist) {185 Integer sum = 0;186 for(Integer integer : list) {187 sum +=integer;188 }189 returnsum;190 }191
192
193 /**
194 * 获取map中第一个key值195 *196 *@parammap 数据源197 *@return
198 */
199 private static Integer getFirstKey(Mapmap) {200 Integer obj = null;201 for (Map.Entryentry : map.entrySet()) {202 obj =entry.getKey();203 if (obj != null) {204 break;205 }206 }207 returnobj;208 }209
210
211 /**
212 * 获取map中第一个数据值213 *214 *@parammap 数据源215 *@return
216 */
217 private static List getFirstValue(Mapmap) {218 List obj = null;219 for (Map.Entryentry : map.entrySet()) {220 obj =entry.getValue();221 if (obj != null) {222 break;223 }224 }225 returnobj;226 }227
228
229 /**
230 * 将[0, 6, 6, 5, 0, 0]231 * [0, 0, 17, 10]232 * [2, 1, 9, 18]中的0去除掉233 *234 *@paramsubList235 */
236 private static List> handZeroEle(List>subList) {237 List> resultList = new ArrayList<>();238 for (Listintegers : subList) {239 List 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 returnresultList;251 }252
253 }