LeetCode 931. 下降路径最小和 1289. 下降路径最小和 II

下降路径最小和
基本上就是数字三角形的翻版

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& a) {
        int n = a.size() ,ans = 1e9;
        vector<vector<int>> dp(n,vector<int>(n,0));
        for(int j=0;j<n;j++){
            dp[0][j] = a[0][j];
        }
        for(int i=1;i<n;i++){
            for(int j=0;j<n;j++){
                dp[i][j] = a[i][j]+dp[i-1][j];
                if(j>0)  dp[i][j] = min(dp[i][j],a[i][j]+dp[i-1][j-1]);
                if(j<n-1) dp[i][j] = min(dp[i][j],a[i][j]+dp[i-1][j+1]);
            }
        }
        for(int j=0;j<n;j++){
            ans = min(ans,dp[n-1][j]);
        }
        return ans;
    }
};
// 1 2 3
// 4 5 6
// 7 8 9

1289. 下降路径最小和 II
会了数字三角形这道题,这道题差不多也会了,本来需要循环遍历出一个最小值,我这里用multiset<int>维护,把时间复杂度降到了 O ( n 2 l o g ( n ) ) O(n^2*log(n))

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& a) {
        int n = a.size();
        vector<vector<int>> dp(n,vector<int>(n));
        for(int j=0;j<n;j++){
            dp[n-1][j] = a[n-1][j];
        }
        for(int i=n-2;i>=0;i--){
            multiset<int> ms;
            for(int j=0;j<n;j++){
                ms.insert(dp[i+1][j]);
            }
            for(int j=0;j<n;j++){
                ms.erase(ms.find(dp[i+1][j]));
                if(j>0) ms.insert(dp[i+1][j-1]);
                int min = *ms.begin();
                dp[i][j] = a[i][j]+min;
            }
        }
        int ans = dp[0][0];
        for(int j=1;j<n;j++){
            ans = min(ans,dp[0][j]);
        }
        return ans;
    }
};

首先一个小技巧,因为是从第一层走到最后一层,所以最后一层是终点,所以好像dp的时候要从后往前推。其实换一种理解方式理解,可以认为层数是一层一层增加的,那么新增加的一层就依赖上一层的状态,这样就可以正着推了。
其次,下一层对上一层依赖,其实仅仅是最大值和次最大值以及产生最大值的角标而已
这样既避免用遍历去获取最小值,也省去了dp数组。
时间复杂度: O ( n 2 ) O(n^2)

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& a) {
        int n = a.size() ,ans = INT_MAX;
        int fms=0,sms=0,jmin=-1;  //初始值置为-1,表明不可能产生冲突
        for(int i=0;i<n;i++){
            int fs = INT_MAX,ss = INT_MAX,jm=-1;
            for(int j=0;j<n;j++){
                int cur_sum = a[i][j]+(j!=jmin?fms:sms);
                if(cur_sum<fs){
                    ss = fs;
                    fs = cur_sum;
                    jm = j;
                }
                else if(cur_sum<ss){
                    ss = cur_sum;
                }
            }
            fms = fs;
            sms = ss;
            jmin= jm;
        }
        return fms;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/107573174