按金额平均批量分配订单算法思考与实现
2017-11-01 16:57
525 查看
1.项目背景
最近遇到需要从经理批量分配订单到主管,主管批量分配订单到人员,我们只需要设计一种算法经理到主管(主管到人类似),尽量保证经理分配到主管的订单的平均金额与数据库里面的平均金额相等。我为此设计了两种算法如下,仅供参考。2.算法以及java实现
2.1 算法1
2.1.1 算法思路
此算法是先传入所有组(一组对应一个主管)需要分配的订单数,按分配的订单数从大到小排序,比如A,B,C三组,订单数为5,3,1。再从数据库里获取一批数据按照订单金额从高到低排序到一个list。比如数据库里订单金额及订单号为(a99,99)...(a1,1)。第一轮分配先取最大的订单金额的分配给A,即A拥有a99,B分配到a98,C分配到a97。第二轮分配最小值,A分配a1,B分配a2,第三轮分配最大值,即A分配a96,B分配a95,以此类推。
2.1.2 算法实现如下
int unallocated = collectionService.findAllUnabsorbedCollectionCount(collectionVo); int assignCount = 0; for(GroupInfoRecord groupInfoRecord : req.getGroupInfoRecord()){ assignCount += groupInfoRecord.getAssignCount(); //获取总分配数 } if(unallocated < assignCount ){ return BusRsp.faild(Constant.CODE_FAILD, "经理未分配总数:"+unallocated+" 需要分配数量之和:"+assignCount+";超出分配数量"); } collectionVo.setCollectionNum(assignCount); //部门分配到组 // 查出分配的订单id List<CollectionPo> collectionIdList = collectionService.findGroupAssignCollectionId(collectionVo); LinkedList<CollectionPo> linkedList = new LinkedList(collectionIdList); //把list转为LinkedList,方便对头尾进行操作 int listSize = linkedList.size(); //先把组进行排序,按照订单量从高到低排序 Map<String,Integer> map = new TreeMap<>(); //key:人员id value: 分配订单数 for(GroupInfoRecord groupInfoRecord : req.getGroupInfoRecord()){ map.put(groupInfoRecord.getGroupId(),groupInfoRecord.getAssignCount()); } //将我们得到的map按照金额降序排列 // 将map.entrySet()转换成list,该list已经按照订单数从大到小排序 List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet()); //降序排序 Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));//这里可转为lambda表达式 // requestNum 代表页面提交的数目 requestGet表示数组当前已经变化的数值 groupIds存放的是requestNum数目对应的人员id int[] requestNum = new int[map.size()]; int[] requestGet = new int[map.size()]; String[] groupIds = new String[map.size()]; int j = 0; //给人员id以及对应的数目赋值 for (Map.Entry<String, Integer> mapping : list) { System.out.println("key:"+mapping.getKey() + " value: " + mapping.getValue()); groupIds[j] = mapping.getKey(); requestNum[j] = mapping.getValue(); j++; } boolean[] requestGetFlag = new boolean[map.size()]; //初始化代表每个组的值都为t 4000 rue,如果该组数目满足要求,则置为false,下一轮不再分配 int index = 0; //代表在某一轮分配中分配给第index+1组 for (int i = 0; i < map.size(); i++){ requestGetFlag[i] = true; } boolean flag; int odd = 0; while (linkedList.size() > 0 && assignCount > 0 ){ flag = true; for (int i = 0; i < map.size(); i++){ if ( 0 == index){ //代表某一轮分配完毕,开始分配下一轮 odd = (odd + 1) % 2; //奇数轮分配最大的,偶数轮分配最小的 } if(requestGetFlag[index] && flag){ assignCount--; //分配一个自减1 requestGet[index]++; //取出订单列表的第一个,直接去数据库更新,此时更新的是map中的第一个,之后变成第二个,第三个 //index+1 代表是第几个groupIds[index+1] linkedList.get(0)表示获取订单list的第一个 分配给第 index + 1个 //针对此订单更新数据库,把该订单分配给groupIds[index+1] //判断订单状态是否已经完成 CollectionPo po = null; int collectionNo = 0 ; if (odd == 1){ collectionNo = 0; } else { collectionNo = linkedList.size()-1 ; } po = collectionService.getById(linkedList.get(collectionNo).getCollectionId()); System.out.println("\n\n*************\n此次分配的订单id为:" + linkedList.get(collectionNo).getCollectionId() + "\n分配给:" + groupIds[index] + "\n***********\n\n"); if(odd == 1){ linkedList.removeFirst(); } else{ linkedList.removeLast(); } flag = false; if (requestGet[index] == requestNum[index]) requestGetFlag[index] = false; index ++; if(index > map.size() - 1){ index = 0; } break; } index ++; if(index > map.size() - 1){ index = 0; } } }
2.1.3 算法的优势与弊端
此算法算是比较简单的一类,一个萝卜一个坑往里填,但是实现起来还是很复杂。对于数据库中存有的数据离散性有一定要求,最好是订单金额的中位数等于或接近平均数。相关文章推荐
- Java仿实现微信红包分配算法
- Java实现红包随机分配算法
- 春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
- 【笔记】从架构到算法,详解美团外卖订单分配内部机制
- 订单生产线分配以及拆分逻辑实现
- 【算法】C语言实现数组的动态分配
- nullnulllinux动态异长存储资源分配算法的实现
- Java权重分配的实现算法
- 大学常见算法的java实现及思考-小老鼠走迷宫(找出一条可行路径即可)
- SAP中如何实现<生产订单>的批量删除方法!
- hadoop实现同一订单中找出最大金额
- linux动态异长存储资源分配算法的实现
- PHP实现微信红包金额拆分试玩的算法示例
- PHP面试题:50,40,30,20,1这五张优惠卷,订单金额为X元,用方法实现return多少张优惠卷
- 内存动态分配的首先适应、最优适应、最坏适应算法的实现(java 版)
- 红包平均分配算法
- 春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
- 数据挖掘-聚类分析:k-平均(k-Means)算法实现(C++)
- 固定金额和人数红包分配算法
- 面积图算法的思考及实现