第 34 场双周赛

学习地址

5491. 矩阵对角线元素的和(遍历)

遍历。对角线特征:i = j || i == n - j - 1

class Solution {
    
    
public:
    int diagonalSum(vector<vector<int>>& mat) {
    
    
        int n = mat.size();

        int res = 0;
        for(int i=0;i<n;i++)
        {
    
    
            res += mat[i][i];
            if(i != n - i - 1) res += mat[i][n - i - 1];
        }

        return res;
    }
};

5492. 分割字符串的方案数(计数)

计数。计数问题一般跟哈希表有关。分3种情况:

  1. 全0
  2. "1"的个数不能整除3
  3. 乘法原理
class Solution {
    
    
public:

    int mod = 1e9 + 7;

    int numWays(string s) {
    
    
        int n = s.size();
        int ones = 0;

        unordered_map<int,int> pos; // 记录位置,分类3有用
        for(int i=0;i<n;i++)
        {
    
    
            if(s[i] == '1'){
    
    
                ones ++;
                pos[ones] = i;
            }
           
        }

        // 分类1
        if(ones == 0) return (long long)(n - 1) * (n - 2) / 2 % mod;
        // 分类2
        if(ones % 3 != 0) return 0;
        // 分类3
        int m =  ones / 3;
        return (long long)(pos[m + 1] - pos[m]) * (pos[m * 2 + 1] - pos[m * 2]) % mod;
        
    }
};

5493. 删除最短的子数组使剩余数组有序(双指针)

假设一下,满足题目要求的必然是 [prefix] [- -][suffix],满足prefix, suffix是递增的,且prefix <= suffix。
这里就可以用双指针算法,边移动边求答案。

class Solution {
    
    
public:
    int findLengthOfShortestSubarray(vector<int>& arr) {
    
    
        if(is_sorted(arr.begin(),arr.end())) return 0; // is_sorted 学来的

        int n = arr.size();
        int l =0 ,r = n- 1;
        while(arr[l] <= arr[l + 1]) l ++ ;
        while(arr[r - 1] <= arr[r]) r -- ;

        int ans = min(n - 1 - l,r);
        // [prefix][-   -][suffix]
        for(int i = 0 , j = r;i <= l && j < n; i ++)
        {
    
    
            while(j < n && arr[j] < arr[i]) j ++;
            if(j < n) ans = min(ans, j - i - 1);
        }

        return ans;
    }
};

5494. 统计所有可行路径(记忆化搜索 ,动态规划)

状态表示 : dp[pos][rest]: 【表示当前在城市pos,剩余油量为rest】这个状态下,到达终点finish的方案数
答案就是 dp[start][fuel]
状态转移:dp[pos][rest] = sum(dp[i][rest - | locations[pos] - locations[i] | ) ( i ! = pos)
如果pos == finish, 对dp[pos][rest] 额外增加1

class Solution {
    
    
public:

    int mod = 1e9 + 7;
    vector<vector<int>> dp;

    int dfs(vector<int>& locations, int pos, int finish, int rest)
    {
    
    
        // 记忆化搜索的精髓
        if(dp[pos][rest] != -1){
    
    
            return dp[pos][rest];
        }

        dp[pos][rest] = 0;
        int n = locations.size();
        for(int i = 0;i < n ;i ++ ){
    
    
            if(pos != i){
    
    
                int cost = abs(locations[pos] - locations[i]);
                if(cost <= rest){
    
    
                    dp[pos][rest] += dfs(locations,i,finish,rest - cost);
                    dp[pos][rest] %= mod;
                }
            }
        }

        if(pos == finish){
    
    
            dp[pos][rest] += 1;
            dp[pos][rest] %= mod;
        }

        return dp[pos][rest];
    }

    int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
    
    
        //dp[postion][rest]: 【表示当前在城市position,剩余油量是rest】这个状态下,到达终点finishi的方案数
        // 答案就是dp[start][fuel]
        // 枚举下一站去哪个城市? 第 i 个城市 dp[position][rest] = 
        // sum(dp[i][rest - |locations[position] - locations[i]|])
        // 如果position == finish 对 dp[position][rest] 额外增加1
        dp.assign(locations.size(),vector<int>(fuel + 1, - 1));
        return dfs(locations,start,finish,fuel);
    }
};

解法2:另一种状态表示

class Solution {
    
    
public:

    long long dp[101][201];
    // 换另一种状态表示
    // dp[i][k] : 剩余油量为k到达 位置i 的方案数
    // 答案 dp[finish][0 .. k];

    // 状态转移 dp[i][k + abs(locations[i] - locations[j])]  += dp[i][k]
    int mod = 1e9 + 7;

    int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
    
    
        memset(dp,0,sizeof dp);
        int n = locations.size();
        
        // 初始化
        dp[start][0] = 1;
        for(int k = 0; k <= fuel; k ++ )
            for(int i = 0; i < n ; i++ )
                for(int j = 0; j < n ;j ++)
                {
    
    
                    if(j == i) continue; // 同一个城市
                    if(k + abs(locations[i] - locations[j]) > fuel) continue;
                    dp[j][k + abs(locations[i] - locations[j])] += dp[i][k];
                    dp[j][k + abs(locations[i] - locations[j])] %= mod;
                }
        
        long long ans = 0;
        for(int k = 0;k <= fuel ;k ++ ){
    
    
            ans = (ans + dp[finish][k]) % mod;
        }

        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43154149/article/details/108436534