算法源于生活,在生活中我们不缺少发现算法的眼睛,这个问题在北京一起租房的舍友提出的:每个人都有自己的消费,对于一起的在一个月或者是两个。
月内实行AA制。这一个月你出了多少钱,我出了多少钱,然后汇总,最后计算谁补偿给谁,以前都是人手统计,然后计算,效率不高,而且费事,作为一个开发工程师,很有必要将这个问题用算法实现出来,下面就是我写的算法。
/**
* 订单实体:就是消费账单
*/
public class Receipt {
private int id;
private long uid;
private double money;
private Date inTime;
private String reMark;
private int state;
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getInTime() {
return inTime;
}
public void setInTime(Date inTime) {
this.inTime = inTime;
}
public String getReMark() {
return reMark;
}
public void setReMark(String reMark) {
this.reMark = reMark;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
补偿实体
public static class Equzlize {
private Long equxUid;//谁
private Long beqUzUid;//给谁
private Double muchMoney;//给多少
public Long getEquxUid() {
return equxUid;
}
public void setEquxUid(Long equxUid) {
this.equxUid = equxUid;
}
public Long getBeqUzUid() {
return beqUzUid;
}
public void setBeqUzUid(Long beqUzUid) {
this.beqUzUid = beqUzUid;
}
public Double getMuchMoney() {
return muchMoney;
}
public void setMuchMoney(Double muchMoney) {
this.muchMoney = muchMoney;
}
//第一组训练数据
// 1 2 3 4 5
// 3 3 4 2 0
// 2.4
// 1 2 3
// 0.6 0.6 1.6
// 4 5
// -0.4 -2.4
//第二组训练数据
// 1 2 3 4 5 6
// 4 5 6 7 8 9
// 6.5
// -2.5 -1.5 -0.5 0.5 1.5 2.5
/**
1->give-->4:---->0.5
1->give-->5:---->1.5
1->give-->6:---->0.5
2->give-->6:---->1.5
3->give-->6:---->0.5
*/
}
核心算法
public static List<Equzlize> getEquzlizeList(List<Receipt> reports, List<Long> uIds) {
List<Equzlize> list = new ArrayList<>();
float allNum = 0;
Map<Long, Double> userToAllMoney = new HashMap<>();
for (Receipt report : reports) {
allNum = allNum + (float) report.getMoney();
if (userToAllMoney.containsKey(report.getUid())) {
userToAllMoney.put(report.getUid(), userToAllMoney.get(report) + report.getMoney());
} else {
userToAllMoney.put(report.getUid(), report.getMoney());
}
}
float avg = allNum / uIds.size();
Map<Long, Double> heightAvgMap = new HashMap<>();//insert
Map<Long, Double> underAvgMap = new ConcurrentHashMap<>();//out
for (int i = 0; i < uIds.size(); i++) {
double d_value = userToAllMoney.get(uIds.get(i)) - avg;
if (d_value > 0) {
heightAvgMap.put(uIds.get(i), d_value);
} else {
underAvgMap.put(uIds.get(i), d_value);
}
}
for (Map.Entry<Long, Double> entry : heightAvgMap.entrySet()) {
double heightAvg = entry.getValue();
double d_money = entry.getValue();
for (Map.Entry<Long, Double> dentry : underAvgMap.entrySet()) {
heightAvg = heightAvg - Math.abs(dentry.getValue());
if (heightAvg < 0) {
Equzlize equzlize = new Equzlize();
equzlize.setEquxUid(dentry.getKey());
equzlize.setBeqUzUid(entry.getKey());
//dentry->entry all
equzlize.setMuchMoney(Math.abs(d_money));
underAvgMap.put(dentry.getKey(), underAvgMap.get(dentry.getKey()) + Math.abs(d_money));
list.add(equzlize);
break;
} else {
Equzlize equzlize = new Equzlize();
equzlize.setEquxUid(dentry.getKey());
equzlize.setBeqUzUid(entry.getKey());
//dentry->entry little
d_money = heightAvg;
equzlize.setMuchMoney(Math.abs(dentry.getValue()));
list.add(equzlize);
underAvgMap.remove(dentry.getKey());
}
}
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getEquxUid() + "->give-->" + list.get(i).getBeqUzUid() + ":---->" + list.get(i).getMuchMoney());
}
return list;
}