46.哀家要长脑子了!

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] 位置能构成符合条件的矩阵的最多数量。那么这个数量可以由它的左边,上边,左上边三个区域中最小的一个来决定。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值