LeetCode 第 34 场双周赛(385/2842,前13.5%)

1. 比赛结果

做出来3题,最后一题动态规划,好难,不会。继续加油!

全国排名: 385 / 2842,13.5%;全球排名: 1149 / 10140,11.3%
在这里插入图片描述

在这里插入图片描述

2. 题目

1. LeetCode 5491. 矩阵对角线元素的和 easy

题目链接

给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。

请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。

示例 1:
在这里插入图片描述

输入:mat = [[1,2,3],
            [4,5,6],
            [7,8,9]]
输出:25
解释:对角线的和为:1 + 5 + 9 + 3 + 7 = 25
请注意,元素 mat[1][1] = 5 只会被计算一次。

示例  2:
输入:mat = [[1,1,1,1],
            [1,1,1,1],
            [1,1,1,1],
            [1,1,1,1]]
输出:8

示例 3:
输入:mat = [[5]]
输出:5
 
提示:
n == mat.length == mat[i].length
1 <= n <= 100
1 <= mat[i][j] <= 100

解题:

一次遍历即可

class Solution {
public:
    int diagonalSum(vector<vector<int>>& mat) {
        int n = mat.size(), sum = 0;
        for(int i = 0; i < n; ++i) 
        {
            sum += mat[i][i]+mat[n-1-i][i];
        }
        if(n&1)
            sum -= mat[n/2][n/2];//奇数时,中间重复了一次
        return sum;
    }
};

32 ms 11.5 MB

2. LeetCode 5492. 分割字符串的方案数 medium

题目链接

给你一个二进制串 s (一个只包含 0 和 1 的字符串),我们可以将 s 分割成 3 个 非空 字符串 s1, s2, s3 (s1 + s2 + s3 = s)。

请你返回分割 s 的方案数,满足 s1,s2 和 s3 中字符 ‘1’ 的数目相同

由于答案可能很大,请将它对 10^9 + 7 取余后返回。

示例 1:
输入:s = "10101"
输出:4
解释:总共有 4 种方法将 s 分割成含有 '1' 数目相同的三个子字符串。
"1|010|1"
"1|01|01"
"10|10|1"
"10|1|01"

示例 2:
输入:s = "1001"
输出:0

示例 3:
输入:s = "0000"
输出:3
解释:总共有 3 种分割 s 的方法。
"0|0|00"
"0|00|0"
"00|0|0"

示例 4:
输入:s = "100100010100110"
输出:12
 
提示:
s[i] == '0' 或者 s[i] == '1'
3 <= s.length <= 10^5

解题:

  • 先检查1的个数能不能被3整除
  • 然后1的个数为0,那么可以有 C n 1 2 C_{n-1}^2 种可能
  • 最后就是2个分界处的 0 的个数+1,再相乘
class Solution {
public:
    int numWays(string s) {
        long long n = s.size(), one = 0;
        for(char c : s)
            if(c == '1')
                one++;
        if(one%3)
            return 0;
        long long o1 = 0, o2 = 0;
        long long n1 = 0, n2 = 0, n3=0;
        for(char c : s)
        {
            if(c == '1')
            {
                if(n1 < one/3)
                    n1++;
                else if(n1 == one/3 && n2 < one/3)
                    n2++;
                else if(n1 == one/3 && n2 == one/3)
                    n3++;
            }
            else
            {
                if(n1 == one/3 && n2 == 0)
                    o1++;
                else if(n1 == one/3 && n2 == one/3 && n3 == 0)
                    o2++;
            }
        }
        if(one == 0)
            return ((n-1)*(n-2)/2)%(int)(1e9+7);
        return (o1+1)*(o2+1)%(int)(1e9+7);
    }
};

116 ms 13.6 MB

3. LeetCode 5493. 删除最短的子数组使剩余数组有序 medium

题目链接

给你一个整数数组 arr ,请你删除一个子数组(可以为空),使得 arr 中剩下的元素是 非递减 的。

一个子数组指的是原数组中连续的一个子序列。

请你返回满足题目要求的最短子数组的长度

示例 1:
输入:arr = [1,2,3,10,4,2,3,5]
输出:3
解释:我们需要删除的最短子数组是 [10,4,2] ,长度为 3 。
剩余元素形成非递减数组 [1,2,3,3,5] 。
另一个正确的解为删除子数组 [3,10,4] 。

示例 2:
输入:arr = [5,4,3,2,1]
输出:4
解释:由于数组是严格递减的,我们只能保留一个元素。
所以我们需要删除长度为 4 的子数组,
要么删除 [5,4,3,2],要么删除 [4,3,2,1]。

示例 3:
输入:arr = [1,2,3]
输出:0
解释:数组已经是非递减的了,我们不需要删除任何元素。

示例 4:
输入:arr = [1]
输出:0
 
提示:
1 <= arr.length <= 10^5
0 <= arr[i] <= 10^9

解题:

  • 找到首尾不满足的地方l, r
  • 可以分三种情况,删除l右侧所有的,或者删除r左侧所有的
  • 或者 删除中间的
class Solution {
public:
    int findLengthOfShortestSubarray(vector<int>& arr) {
        int n = arr.size(), i, j, l = -1, r = -1;
        for(i = 1; i < n; ++i) 
        {
            if(arr[i-1] > arr[i])
            {
                l = i-1;
                break;
            }
        }
        if(l == -1)
            return 0;
        for(i = n-2; i >= 0; --i)
        {
            if(arr[i] > arr[i+1])
            {
                r = i+1;
                break;
            }
        }
        int ans = min(n-l-1, r);//删除右侧的、或者删除左侧的
        i = 0, j = r;
        while(i <= l && j < n)//或者 处理中间部分
        {
            if(arr[i] <= arr[j])
            {
                ans = min(ans, j-i-1);
                i++;
            }
            else
                j++;
        }
        return ans;
    }
};

296 ms 66.8 MB

4. LeetCode 5494. 统计所有可行路径 hard

题目链接

给你一个 互不相同 的整数数组,其中 locations[i] 表示第 i 个城市的位置。
同时给你 start,finish 和 fuel 分别表示出发城市、目的地城市和你初始拥有的汽油总量

每一步中,如果你在城市 i ,你可以选择任意一个城市 j ,满足 j != i 且 0 <= j < locations.length ,并移动到城市 j 。
从城市 i 移动到 j 消耗的汽油量为 |locations[i] - locations[j]||x| 表示 x 的绝对值。

请注意, fuel 任何时刻都 不能 为负,且你 可以 经过任意城市超过一次(包括 start 和 finish )。

请你返回从 start 到 finish 所有可能路径的数目

由于答案可能很大, 请将它对 10^9 + 7 取余后返回。

示例 1:
输入:locations = [2,3,6,8,4], start = 1, finish = 3, fuel = 5
输出:4
解释:以下为所有可能路径,每一条都用了 5 单位的汽油:
1 -> 3
1 -> 2 -> 3
1 -> 4 -> 3
1 -> 4 -> 2 -> 3

示例 2:
输入:locations = [4,3,1], start = 1, finish = 0, fuel = 6
输出:5
解释:以下为所有可能的路径:
1 -> 0,使用汽油量为 fuel = 1
1 -> 2 -> 0,使用汽油量为 fuel = 5
1 -> 2 -> 1 -> 0,使用汽油量为 fuel = 5
1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 3
1 -> 0 -> 1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 5

示例 3:
输入:locations = [5,2,1], start = 0, finish = 2, fuel = 3
输出:0
解释:没有办法只用 3 单位的汽油从 0 到达 2 。
因为最短路径需要 4 单位的汽油。

示例 4 :
输入:locations = [2,1,5], start = 0, finish = 0, fuel = 3
输出:2
解释:总共有两条可行路径,00 -> 1 -> 0 。

示例 5:
输入:locations = [1,2,3], start = 0, finish = 2, fuel = 40
输出:615088286
解释:路径总数为 2615088300 。
将结果对 10^9 + 7 取余,得到 615088286 。
 
提示:
2 <= locations.length <= 100
1 <= locations[i] <= 10^9
所有 locations 中的整数 互不相同 。
0 <= start, finish < locations.length
1 <= fuel <= 200

解题:

学习了大佬的题解

  • dp[city][f] 表示到达city时,花费了 f燃料的方案数
class Solution {
public:
    int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
    	int n = locations.size(), i, j, f, mod = 1e9+7;
    	vector<vector<int>> dp(n, vector<int>(fuel+1, 0));
    	dp[start][0] = 1; // 到达 i 城市,花了 f 油的方案数
		for(f = 0; f <= fuel; ++f)//遍历燃料
		{
			for(i = 0; i < n; ++i)//前一个城市
			{
				for(j = 0; j < n; ++j)//转移到的城市
				{
					if(i == j)
						continue;
					if(dp[i][f] != 0 && f+abs(locations[i]-locations[j]) <= fuel)
					{	//前一个状态存在,且可以到达下一个状态
						dp[j][f+abs(locations[i]-locations[j])] += dp[i][f];
						dp[j][f+abs(locations[i]-locations[j])] %= mod;
					}
				}
			}
		}
		int ans = 0;
		for(f = 0; f <= fuel; f++)
			ans = (ans+dp[finish][f])%mod;
			//所有燃料情况下,到达终点的方案之和
		return ans;
    }
};

440 ms 12.2 MB


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

猜你喜欢

转载自blog.csdn.net/qq_21201267/article/details/108426333