java实战算法根据个数百分比,排序金额分配案件金额也趋近百分比

使用场景:

给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();
	}


将分完的结果通过对象返回给前台页面


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值