给你一个整数
finalSum。请你将它拆分成若干个 互不相同 的正偶数之和,且拆分出来的正偶数数目 最多 。
- 比方说,给你
finalSum = 12,那么这些拆分是 符合要求 的(互不相同的正偶数且和为finalSum):(2 + 10),(2 + 4 + 6)和(4 + 8)。它们中,(2 + 4 + 6)包含最多数目的整数。注意finalSum不能拆分成(2 + 2 + 4 + 4),因为拆分出来的整数必须互不相同。请你返回一个整数数组,表示将整数拆分成 最多 数目的正偶数数组。如果没有办法将
finalSum进行拆分,请你返回一个 空 数组。你可以按 任意 顺序返回这些整数。
首先看到题目的要求,首先想到的就是回溯,结果超时,哎,不过也回忆了一下动态规划 + 递归
public List<Long> maximumEvenSplit(long finalSum) {
if (finalSum % 2 > 0) {
return new ArrayList<>();
}
HashMap<Long, List<List<Long>>> memory = new HashMap<>();
List<List<Long>> lists = all_Construct(finalSum, memory);
int maxLength = 0;
int index = 0;
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).size() > maxLength) {
maxLength = lists.get(i).size();
index = i;
}
}
return lists.get(index);
}
public List<List<Long>> all_Construct(long finalSum, HashMap<Long, List<List<Long>>> memory) {
if (memory.containsKey(finalSum)) return memory.get(finalSum);
if (finalSum == 0) return new ArrayList<>(Arrays.asList(new ArrayList<>()));
List<List<Long>> result = new ArrayList<>();
for (long num = 2; num <= finalSum; num = num + 2) {
long suffix = finalSum - num;
List<List<Long>> suffixWays = all_Construct(suffix, memory);
List<List<Long>> targetWays = new ArrayList<>();
for (List<Long> suffixWay : suffixWays) {
List<Long> temp = new ArrayList<>(suffixWay);
if (!temp.contains(num)) {
temp.add(num);
targetWays.add(temp);
}
}
result.addAll(targetWays);
}
memory.put(finalSum, result);
return result;
}
正确的解法是向官网所写一样,使用贪心,要想长度最长,那么每次分解的数就要最小,那么从2开始遍历即可
public List<Long> maximumEvenSplit(long finalSum) {
if (finalSum % 2 > 0) {
return new ArrayList<>();
}
List<Long> result = new ArrayList<>();
for (long i = 2; i <= finalSum; i = i + 2) {
result.add(i);
finalSum = finalSum - i;
}
result.set(result.size() - 1, result.get(result.size() - 1) + finalSum);
return result;
}