题目:m个含有n位数字的数组排列组合选出最大的k个值
在面试阿里的过程中收到了一道面试题,题目意思主要就是在m个含有n位数字的数组排列组合选出最大的k个值,提供一种解题方法,看到题目的第一时间肯定会想到排列组合出所有可能然后进行排序选取最高几位。但是在数组多及数组含有数字庞大的时候,这种方法效率是非常低下的,我想到了一种解题思路,在此记录,由于时间匆忙,代码可能有很多漏洞和不足,仅作参考。
解题思路
假如有a[],b[],c[]三个队列,首先将三个队列从大到小做一个排序,明确f(0,0,0)表示a[0],b[0],c[0]之和,
那么f(0,0,0)即为最大值,由于三个队列都从大到小排序,所以仅次于f(0,0,0)的第二大值只可能从f(1,0,0),f(0,1,0),f(0,0,1)中产生,
然后将f(1,0,0),f(0,1,0),f(0,0,1)加入比较队列,比较队列的最大值即为所有可能结果中的第二大值,同时在比较队列中删除该值,
假设f(1,0,0)为第二大值,再f(1,0,0),f(0,1,0),f(0,0,1)队列中删除f(1,0,0),变成f(0,1,0),f(0,0,1),取f(2,0,0),f(1,1,0),f(1,0,1)加入比较队列和剩余的f(0,1,0),f(0,0,1)比较,最大值即为所有可能结果中的第二大值并删除该值
假设f(1,0,1)为第三大额度,取f(2,0,1),f(1,1,1),f(1,0,2)加入比较队列和剩余值比较,依次比较完成。
代码实现(可能有很多疏漏,仅供参考)
package ali;
import java.util.*;
public class AliTest {
/**
* 求店铺券最佳组合 排列组合
*
* @param combinationLists 各店铺优惠券组合列表 即为排列组合队列
*/
public static LinkedList<Integer> getBestCombinationTwo(List<List<Coupon>>... combinationLists) {
//TOP 5最佳组合
LinkedList<Integer> bestCombination = new LinkedList<>();
//各个店铺每个组合优惠券总金额列表
List<List<Integer>> shopsOfCombinationSum = new ArrayList<>();
//循环获取每个店铺优惠券组合列表 统计每个店铺每种组合总额
for (List<List<Coupon>> combinationList : combinationLists) {
//单个店铺每个组合减免总金额汇总列表
List<Integer> oneShopCombinationSum = new ArrayList<>();
//循环每个店铺优惠券组合
for (List<Coupon> combination : combinationList) {
//该组合优惠券总额
int sum = combination.stream().mapToInt(Coupon::getDiscountAmount).sum();
oneShopCombinationSum.add(sum);
}
oneShopCombinationSum.sort((o1, o2) -> o2 - o1);
shopsOfCombinationSum.add(oneShopCombinationSum);
}
//店铺数
int length