算法每一题,成长每一天~
C0E15 最长连续子序列
真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)
思路
完全没有思路。
然后 deepseek 用了6分钟十几页的分析,给出了答案。
思路如下:
…
将其当做一个《背包问题》,但是需要恰好装满背包(即“重量”必需等于sum而不是小于等于)。
期间 deepseek 分析了很多贪心算法的思路,最后发现不可取,仍然回归到 动态规划 上。
Java
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
public class C0E15 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String line = in.nextLine();
int R = in.nextInt();
List<Integer> numList =
Arrays.stream(line.split(","))
.map(Integer::parseInt)
.sorted() // 小到大排序
.collect(Collectors.toList());
int[] dp = new int[R + 1];
Arrays.fill(dp, Integer.MIN_VALUE); // 赋初始值,-1 或 -∞ 都行
dp[0] = 0; // 初始条件:和为0时,0个数
for (int num : numList) {
if (num > R) {
break; // 后面的数都比目标大,直接结束
}
for (int j = R; j >= num; j--) { // 这里必需 从大到小 遍历,确保每个 num 只用一遍
// if=true表示:总和 j-num,可以通过前面已经遍历过的数组合得到,且 dp[j-num] 就是组合的最大个数
if (dp[j - num] != Integer.MIN_VALUE) {
// 那么:总和为 j 的最大个数 等于 dp[j-num] + 1
dp[j] = Math.max(dp[j], dp[j - num] + 1);
}
}
}
// 测例:[1,1,2,3,20,20,30,40], R=32
System.out.println(dp[R] > 0 ? dp[R] : -1);
}
}
总结
1、deepseek的解释
2、典型题目!《0-1背包问题》的变种。
- 普通背包问题,只要能装得下的情况下,求最大值。
- 这里要求,必需恰好装满的情况下,求最大值。
3、测例运行结果
测例:
1,1,2,3,20,20,30,40
32
dp[]结果如下:
0 = 0
1 = 1
2 = 2
3 = 2
4 = 3
5 = 3
6 = 3
7 = 4
8 = -2147483648
9 = -2147483648
10 = -2147483648
11 = -2147483648
12 = -2147483648
13 = -2147483648
14 = -2147483648
15 = -2147483648
16 = -2147483648
17 = -2147483648
18 = -2147483648
19 = -2147483648
20 = 1
21 = 2
22 = 3
23 = 3
24 = 4
25 = 4
26 = 4
27 = 5
28 = -2147483648
29 = -2147483648
30 = 1
31 = 2
32 = 3
可以看到,在必需恰好装满的情况下,有些值是不可达的(= -2147483648),即:无法通过任何组合得到这个值。
4、这里如果要输出最长组合的每个数,该怎么做呢?
算法要多练多练多练!!