题目是找3个长度为k的不重叠的子数组,和最大。
错误思路:
一开始理解成不重合,只要有一个不同就是不同的子数组。所以先用滑动窗口生成了所有长度为k的子数组的和,选和最大的前3个。
后来发现是不重叠,想用贪心,先选和最大的子区间,然后选不重叠的和最大的。知道这样不一定保证最优解,尝试选前10大的子区间,再从比它小的子区间里选不重叠的最大的。
代码如下
private boolean chongDie(int b, List<Integer> a, int k) {
for (int t : a) {
if (Math.abs(b - t) < k) {
return true;
}
}
return false;
}
public int[] maxSumOfThreeSubarrays2(int[] nums, int k) {
long cur = 0L;
List<Pair<Long, Integer>> list = new ArrayList<>();
for (int i = 0; i < k; i++) {
cur += nums[i];
}
list.add(new Pair<>(cur, 0));
for (int i = k; i < nums.length; i++) {
cur -= nums[i - k];
cur += nums[i];
list.add(new Pair<>(cur, i - k + 1));
}
System.out.println(list);
list.sort(new Comparator<Pair<Long, Integer>>() {
@Override
public int compare(Pair<Long, Integer> o1, Pair<Long, Integer> o2) {
if (o1.getKey().equals(o2.getKey())) {
if (o1.getValue() < o2.getValue()) {
return -1;
}
} else if (o1.getKey() < o2.getKey()) {
return 1;
} else if (o1.getKey() > o2.getKey()) {
return -1;
}
return 0;
}
});
System.out.println(list);
long sum = 0L;
int[] ans = new int[3];
for (int st = 0; st < Math.min(10, list.size()); st++) {
cur = 0L;
List<Integer> res = new ArrayList<>();
res.add(list.get(st).getValue());
cur += list.get(st).getKey();
for (int i = st + 1; i < list.size(); i++) {
if (!chongDie(list.get(i).getValue(), res, k)) {
cur += list.get(i).getKey();
res.add(list.get(i).getValue());
if (res.size() == 3) {
break;
}
}
}
if (cur > sum) {
Collections.sort(res);
for (int i = 0; i < 3; i++) {
ans[i] = res.get(i);
}
sum = cur;
}
}
return ans;
}
对于输入
[17,7,19,11,1,19,17,6,13,18,2,7,12,16,16,18,9,3,19,5]
6
我的输出为
[0,6,12]
正确的输出是
[0,6,13]
分析一下,长度为k的子区间如下:
[74=0, 74=1, 73=2, 67=3, 74=4, 75=5, 63=6, 58=7, 68=8, 71=9, 71=10, 78=11, 74=12, 81=13, 70=14]
[81=13, 78=11, 75=5, 74=0, 74=1, 74=4, 74=12, 73=2, 71=9, 71=10, 70=14, 68=8, 67=3, 63=6, 58=7]
我的程序没有选13,它选的第一个最长的是12。
因为选13,后面选的还是贪心,最终选的是13、5,还是不能保证最优解。所以我的程序选13的结果没有答案的优。