java實戰演算法根據個數百分比,排序金額分配案件金額也趨近百分比
阿新 • • 發佈:2019-02-09
使用場景:
給n個員工分配n個案子。條件是按個數比例分配。分配後的案件金額也趨近於個數的比例,並且趨近公平分配。
設計思路
這裡比較複雜的地方就是怎麼按個數佔比分配,案件金額總數也趨近個數佔比。並且趨近公平
例如10個按鍵,案件金額為1,2,3,4,5,6,7,8,9,10
第一種情況偶數分配:
給兩個人分案件,一個分配40%一個分配60%,案件個數就是4:6 = 2:3 怎麼讓金額也趨近2:3
設計思路是先將案件按金額大小排序從頭尾獲取,第一個人獲取四個案件,這四個案件分別從頭尾獲取,例如當A先獲取四個案件是,A拿到的案件分別是1,10,2,9。B獲取到的就是3,8,4,7,5,6,金額的比例是 22:33 趨近 2:3的案件佔比。
第二種情況奇數數分配:
給兩個人分案件,一個分配30%一個分配70%,案件個數就是3:7怎麼讓金額也趨近3:7=0.42設計思路是還是先將案件按金額大小排序從頭尾獲取,第一個人獲取四個案件,這四個案件分別從頭尾獲取,例如當 A先獲取一箇中間的案件然後剩下的按偶數的從頭尾取案件,同理第二個人也一樣A拿到的案件分別是5,1,10 B獲取到的就是6,2,9,3,8,4,7 金額的比例是 16:39=0.41趨近於0.42的案件佔比。
當總件數跟百分比的乘機為有小數點的時候,向下取整,比如1.4 取 1。最後一個人直接取剩下所有。
偶數分配圖示
奇數分配圖示
Java程式碼:
//*********************************************催收公司分案相關**************************// @Override public List<User> updateAutoCaseSplit(CaseHead head,CaseParamsExtend exParams,List<User> users,String tableName) { if (head == null){ return users; } if (users == null || users.size() == 0){ return users; } //獲取案件 List<CaseHead> heads=caseHeadMapper.getCaseHeadAll(head,exParams,tableName); if (heads == null || heads.size() == 0){ return users; } // 進行分案處理 1.案件金額排序 sortCases(heads); Integer casecount=heads.size();//案件個數 //將使用者排序打亂 Collections.shuffle(users); List<CaseHead> caselist=new ArrayList<CaseHead>();//剩餘案件 caselist=heads; //迴圈遍歷員工 for (int i = 0; i <users.size() ; i++) { //計算使用者分得幾個案子 案件數*百分比 if (i != users.size()-1){ double userCaseCount=casecount*users.get(i).getSplitRate()/100; Integer count=(int)Math.floor(userCaseCount); //根據分的案件個數從頭尾取值 如果有奇數就奇數在中間取一個變為偶數在頭尾取值 if (count%2==0){//偶數 Integer total=count/2; //頭尾各取total個 for (int j = 0; j < total; j++) { int end=caselist.size()-1; users.get(i).addCaseHead(caselist.get(0));//頭 users.get(i).addCaseHead(caselist.get(end));//尾 caselist.remove(end); caselist.remove(0); } }else{//奇數 if (count == 1){//如果只有一個案子那麼在中間取一個就退出 int middle=(int)Math.floor(caselist.size()/2); users.get(i).addCaseHead(caselist.get(middle));//中 caselist.remove(middle); }else{ //第一個取中間 int middle=(int)Math.floor(caselist.size()/2); users.get(i).addCaseHead(caselist.get(middle));//中 caselist.remove(middle); //剩下的跟偶數一致 int total=(count-1)/2; for (int a = 0; a < total; a++) { int end=caselist.size()-1; users.get(i).addCaseHead(caselist.get(0));//頭 users.get(i).addCaseHead(caselist.get(end));//尾 caselist.remove(end); caselist.remove(0); } } } }else{//最後一個不用計算案件數。剩餘案件全是最後一個的這是為了以上幾個計算有小數點取整誤差 for (CaseHead caseHead : caselist) { users.get(i).addCaseHead(caseHead); } } } return users; } /** * 執行分案 * */ @Override public List<User> updateCaseSplit(List<User> users, String tableName) throws Exception { for (int i = 0; i <users.size() ; i++) { } return null; } //案件按照金額排序 private void sortCases(List<CaseHead> caseHeads) { Collections.sort(caseHeads, new Comparator<CaseHead>() { @Override public int compare(CaseHead o1, CaseHead o2) { return (int) (o2.getMoney() - o1.getMoney()) * 1000; } }); } //*********************************************催收公司分案相關結束************************//
//==================分案相關操作
@Transient
private double splitRate;//分案佔比;
@Transient
private double splitTotal;//分案總金額
@Transient
private int splitCount;//分案總件數
@Transient
private List<User> userList;//分案引數
@Transient
private List<CaseHead> caseList;//案件list
public List<CaseHead> getCaseList() {
return caseList;
}
public void setCaseList(List<CaseHead> caseList) {
this.caseList = caseList;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void addCaseHead(CaseHead caseHead){
if(caseList==null)
caseList=new ArrayList<>();
caseList.add(caseHead);
//總額 件數
splitCount++;
splitTotal+=caseHead.getMoney();
}
將分完的結果通過物件返回給前臺頁面