1.435. 无重叠区间 - 力扣(LeetCode)
方法一:动态规划
实际上本质就是找最长的无重叠子序列,那么我们可以遍历这个区间的集合,只要前一个区间的右端点是小于等于后一个区间的左端点,那么这两个区间就不是重合的。用一个数组来存储到每个区间的最长非重叠子序列长度。即 f[i] 就是第i个区间为结尾的非重叠子序列的长度。 每一个区间的计算可以根据上一个区间的情况结合现在区间加入的情况来计算。这就是动态规划的思想体现。将动态规划数组f 所有元素初始化为1 的原因是,每个区间至少有一个不重叠的子序列就是它寄几本身
C++版:
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int n = intervals.size();
if(n == 0) return 0;
sort(intervals.begin(), intervals.end(), [](const auto &u, const auto &v){
return u[1] < v[1];
});
vector<int> f(n, 1);
for(int i = 1; i < n; i++) {
for(int j = 0; j < i; j++) {
if(intervals[i][0] >= intervals[j][1])
f[i] = max(f[i], f[j]+1);
}
}
return n - *max_element(f.begin(), f.end());
}
};
Java版:
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int n = intervals.length;
if(n == 0) return 0;
Arrays.sort(intervals, new Comparator<int[]> (){
public int compare(int[] u, int[] v){
return u[1] - v[1];
}
});
int[] f = new int[n];
Arrays.fill(f, 1);
for(int i = 1; i < n; i++) {
for(int j = 0; j < i; j++) {
if(intervals[i][0] >= intervals[j][1]) {
f[i] = Math.max(f[i], f[j]+1);
}
}
}
return n - Arrays.stream(f).max().getAsInt();
}
}
但是动态规划的时间复杂度太高了,leetcode最后几个很大的数据过不了,会超时。
方法二:贪心
其实我觉得这道题中贪心和动态规划的本质思想是一样的,都是在以区间的右端点升序排序后,比较前一个区间的右端点和后一个区间的左端点大小,以此来判断两个区间是否重叠。只是操作不同,贪心的操作不是用双重循环来遍历,数组来存储。而是在每一次的比较后,遇到非重叠的区间,将旗帜right变量中的右端点不断迭代更新。
C++版
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int n = intervals.size();
if(n == 0) return 0;
sort(intervals.begin(), intervals.end(), [](const auto &u, const auto &v){
return u[1] < v[1];
});
int right = intervals[0][1]; // 第一个区间的右端点
int ans = 1;
for(int i = 1; i < n; i++) {
if(intervals[i][0] >= right) {
ans++;
right = intervals[i][1];
}
}
return n - ans;
}
};
Java版
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int n = intervals.length;
if(n == 0) return 0;
Arrays.sort(intervals, new Comparator<int[]> (){
public int compare(int[] u, int[] v){
return u[1] - v[1];
}
});
int ans = 1;
int right = intervals[0][1];
for(int i = 1; i < n; i++) {
if(intervals[i][0] >= right) {
ans++;
right = intervals[i][1];
}
}
return n - ans;
}
}
2.1502. 判断能否形成等差数列 - 力扣(LeetCode)
Java版:
class Solution {
public boolean canMakeArithmeticProgression(int[] arr) {
Arrays.sort(arr);
int dif = arr[1] - arr[0];
for(int i = 1; i < arr.length; i++) {
if(arr[i] - arr[i-1] != dif)
return false;
}
return true;
}
}
骚瑞啊 直接排序加遍历判断的
3.1277. 统计全为 1 的正方形子矩阵 - 力扣(LeetCode)
C++版:
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n, vector<int>(m));
int res = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(i == 0 || j == 0) f[i][j] = matrix[i][j]; // 它自己本身
else if(matrix[i][j] == 0) f[i][j] = 0;
else f[i][j] = min(min(f[i-1][j], f[i][j-1]), f[i-1][j-1]) + 1;
res += f[i][j];
}
}
return res;
}
};
Java版
class Solution {
public int countSquares(int[][] matrix) {
int n = matrix.length, m = matrix[0].length;
int[][] f = new int[n][m];
int res = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(i == 0 || j == 0) f[i][j] = matrix[i][j];
else if(matrix[i][j] == 0) f[i][j] = 0;
else f[i][j] = Math.min(Math.min(f[i-1][j], f[i][j-1]), f[i-1][j-1]) + 1;
res += f[i][j];
}
}
return res;
}
}
怎么说。。。我不知道说。。。我似懂非懂。。。我不知所措。。。我想吃山东巧饼。。。
f 数组存储的是 每个[i, j] 位置能构成符合条件的矩阵的最多数量。那么这个数量可以由它的左边,上边,左上边三个区域中最小的一个来决定。