https://blog.csdn.net/qq_39382769/article/details/80788294
dp先分解成很多相互联系的子问题,要解决一个子问题,依赖于前面和此子问题相关的已经解决的子问题中选一个最优的 加上这个子问题的解,就是这个子问题的最优解
dp和分治的不同之处在于
分治分解而成的子问题必须没有联系
dp和贪心的不同之处在于
每一次的贪心都是做出不可撤回的决策(即每次局部最优)
题目
https://leetcode.cn/problems/two-best-non-overlapping-events/description/?languageTags=java
// http://3ms.huawei.com/km/groups/2692001/home?l=zh-cn&moduleId=628048024761630720#category=9076663
public class test {
public static void main(String[] args) {
// int[][] events = new int[][]{{1, 3, 2}, {4, 5, 2}, {2, 4, 3}};
// int[][] events = new int[][]{{1,5,3},{1,5,1},{6,6,5}};
int[][] events = new int[][]{{1, 3, 2}, {4, 5, 2}, {2, 4, 3}};
System.out.println(maxTwoEvents(events));
}
public static int maxTwoEvents(int[][] events) {
Arrays.sort(events, Comparator.comparing(e -> e[1]));
int[][] dp = new int[events.length][3];
dp[0][1] = events[0][2];
dp[0][2] = events[0][2];
int length = events.length;
for (int i = 1; i < length; i++) {
dp[i][1] = Math.max(dp[i - 1][1], events[i][2]);
// int j = i - 1;
// while (events[j][1] >= events[i][0]) {
// j--;
// if (j < 0)
// break;
// }
var left = 0;
var j = i - 1;
var mid = (left + j) / 2;
while (left <= j) {
if (events[mid][1] < events[i][0]) {
left = mid + 1;
} else {
j = mid - 1;
}
mid = (left + j) / 2;
}
if (j >= 0) {
dp[i][2] = dp[j][1] + events[i][2];
}
dp[i][2] = Math.max(dp[i][2], dp[i - 1][2]);
}
return Math.max(dp[length - 1][1], dp[length - 1][2]);
}
}
贪心
class Node implements Comparable<Node> {
int left;
int right;
public Node(int left, int right) {
this.left = left;
this.right = right;
}
@Override
public int compareTo(Node o) {
if (right == o.right)
return o.left - left;
return right - o.right;
}
}
// https://leetcode.cn/problems/maximum-number-of-non-overlapping-substrings/
public class test2 {
public static void main(String[] args) {
String s = "adefaddaccc";
System.out.println(maxNumOfSubstrings(s));
}
public static List<String> maxNumOfSubstrings(String s) {
Node[] nodes = new Node[26];
for (int i = 0; i < 26; i++) {
nodes[i] = new Node(-1, -1);
}
int length = s.length();
for (int i = 0; i < length; i++) {
int j = s.charAt(i) - 'a';
if (nodes[j].left == -1) {
nodes[j].left = i;
}
nodes[j].right = i;
}
for (int i = 0; i < 26; i++) {
if (nodes[i].left == -1)
continue;
for (int j = nodes[i].left + 1; j < nodes[i].right; j++) {
int charAt = s.charAt(j) - 'a';
if (nodes[i].left <= nodes[charAt].left && nodes[i].right >= nodes[charAt].right)
continue;
nodes[i].left = Math.min(nodes[i].left, nodes[charAt].left);
nodes[i].right = Math.max(nodes[i].right, nodes[charAt].right);
j = nodes[i].left;
}
}
Arrays.sort(nodes);
List<String> ans = new ArrayList<>();
int end = -1;
for (int i = 0; i < 26; i++) {
if (nodes[i].left == -1)
continue;
if (nodes[i].left > end) {
ans.add(s.substring(nodes[i].left, nodes[i].right + 1));
end = nodes[i].right;
}
}
return ans;
}
}
46 - 47 行代码 不可或缺
没有它的话,就是死循环了