mysql 数组找最少_算法最少分组法-将数组arr中的数字分组,要求各个分组中数字之和小于等于k,求最小分组数的情况,默认arr中每个数均小于k...

该算法实现将整数数组arr分组,确保每个组内数字之和不超过k,目标是最小化分组数量。首先对数组进行排序,然后依次累加元素,当和超过k时创建新组。接着,对除第一个组之外的其他组按剩余和D[i]升序排序,通过迭代和调整,尝试将大数分配到合适的组中,直至无法再进行分裂。最后处理包含0的组,返回最小分组结果。
摘要由CSDN通过智能技术生成

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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值