一定,每个人都没有责任,都没有错,每个人都拼尽了全力。

t2不错,前缀和有时也是快速寻求最优解的技巧,t4是道不错的DP解,需要优化。
推荐VP。
更多解题报告详见:珂朵莉MM的解题报告汇总
解法蛮多的,数据结构也蛮多的。
因为数据范围较小(),所以用数组来直接代替Hash表。
class Solution {
public int sumOfUnique(int[] nums) {
int[] used = new int[101];
for (int v: nums) {
used[v]++;
}
int ans = 0;
for (int v: nums) {
if (used[v] == 1) {
ans += v;
}
}
return ans;
}
}前缀和的优化技巧,感觉蛮重要的.
区间和绝对值最大,等价于区间和要么最大,要么最小。
这边固定右端点,那么结果等价于
以端点为右端点的区间绝对值最大和为:
其中:
而这个有点像DP优化中,常见到的单调队列优化技巧。
class Solution {
public int maxAbsoluteSum(int[] nums) {
long ans = Math.abs(nums[0]);
long max = 0, min = 0;
long acc = 0;
for (int i = 0; i < nums.length; i++) {
acc += nums[i];
max = Math.max(max, acc);
min = Math.min(min, acc);
ans = Math.max(ans, Math.max(Math.abs(acc - max), Math.abs(acc - min)));
}
return (int)ans;
}
}
简单的贪心题,用双指针就行。
class Solution {
public int minimumLength(String s) {
// 贪心算法
char[] buf = s.toCharArray();
int i = 0, j = buf.length - 1;
while (i < j) {
char c = buf[i];
if (buf[j] != c) break;
// 左边移动
while (i <= j) {
if (buf[i] == c) {
i++;
} else {
break;
}
}
// 右边移动
while (i <= j) {
if (buf[j] == c) {
j--;
} else {
break;
}
}
}
return j - i + 1;
}
}最优化问题,要么是贪心,要么是DP。
但无论贪心,还是DP,首先要排序,这边按右端点作为排序的第一基准。
在看数据范围,特别有意思,一般两个变量相乘表示的范围,往往是DP。
那么这个最优化问题,其DP解就非常的清晰了。
其中容易处理,合并项即可,但是区间不想交,这个时候之前的排序就其作用了,因为根据右端点排序,只要找到当前区间的左端点为基准,二分找到最近的右端点j即可。
在LC中的dp题中,这个dp算是比较特殊的。
class Solution {
// 二分找到 lowerbound界
int search(int[][] events, int idx) {
int x = events[idx][0];
int l = 0, r = idx;
while (l <= r) {
int m = l + (r - l) / 2;
if (events[m][1] >= x) {
r = m - 1;
} else {
l = m + 1;
}
}
return r;
}
public int maxValue(int[][] events, int k) {
int n = events.length;
long[][] opt = new long[n][k + 1];
// 先排序
Arrays.sort(events, (a, b) -> {
if (a[1] != b[1]) return a[1] < b[1] ? -1 : 1;
if (a[0] != b[0]) return a[0] < b[0] ? -1 : 1;
return 0;
});
Arrays.fill(opt[0], -1);
opt[0][0] = 0;
opt[0][1] = events[0][2];
for (int i = 1; i < n; i++) {
// 复制(这个很重要)
for (int j = 0; j <= k; j++) {
opt[i][j] = opt[i - 1][j];
}
// 然后优化
int p = search(events, i);
if (p == -1) {
opt[i][1] = Math.max(opt[i][1], events[i][2]);
} else {
for (int j = 0; j < k; j++) {
if (opt[p][j] == -1) {
break;
}
if (opt[i][j + 1] == -1 || opt[i][j + 1] < opt[p][j] + events[i][2]) {
opt[i][j + 1] = opt[p][j] + events[i][2];
}
}
}
}
long ans = 0;
for (int i = 1; i <= k; i++) {
if (opt[n - 1][i] != -1) {
ans = Math.max(ans, opt[n - 1][i]);
}
}
return (int)ans;
}
}