LeetCode353场周赛题解

126 阅读4分钟

353场周赛

6451. 找出最大的可达成数字

给你两个整数 numt

如果整数 x 可以在执行下述操作不超过 t 次的情况下变为与 num 相等,则称其为 可达成数字

  • 每次操作将 x 的值增加或减少 1 ,同时可以选择将 num 的值增加或减少 1

返回所有可达成数字中的最大值。可以证明至少存在一个可达成数字。

示例 1:

 输入:num = 4, t = 1
 输出:6
 解释:最大可达成数字是 x = 6 ,执行下述操作可以使其等于 num :
 - x 减少 1 ,同时 num 增加 1 。此时,x = 5 且 num = 5 。 
 可以证明不存在大于 6 的可达成数字。

示例 2:

 输入:num = 3, t = 2
 输出:7
 解释:最大的可达成数字是 x = 7 ,执行下述操作可以使其等于 num :
 - x 减少 1 ,同时 num 增加 1 。此时,x = 6 且 num = 4 。 
 - x 减少 1 ,同时 num 增加 1 。此时,x = 5 且 num = 5 。 
 可以证明不存在大于 7 的可达成数字。

提示:

  • 1 <= num, t <= 50

num + t = x - t即:x = num + 2 * t

 class Solution {
 public:
     int theMaximumAchievableX(int num, int t) {
         return num + t * 2;
     }
 };

6899. 达到末尾下标所需的最大跳跃次数

给你一个下标从 0 开始、由 n 个整数组成的数组 nums 和一个整数 target

你的初始位置在下标 0 。在一步操作中,你可以从下标 i 跳跃到任意满足下述条件的下标 j

  • 0 <= i < j < n
  • -target <= nums[j] - nums[i] <= target

返回到达下标 n - 1 处所需的 最大跳跃次数

如果无法到达下标 n - 1 ,返回 -1

示例 1:

 输入:nums = [1,3,6,4,1,2], target = 2
 输出:3
 解释:要想以最大跳跃次数从下标 0 到下标 n - 1 ,可以按下述跳跃序列执行操作:
 - 从下标 0 跳跃到下标 1 。 
 - 从下标 1 跳跃到下标 3 。 
 - 从下标 3 跳跃到下标 5 。 
 可以证明,从 0 到 n - 1 的所有方案中,不存在比 3 步更长的跳跃序列。因此,答案是 3 。 

示例 2:

 输入:nums = [1,3,6,4,1,2], target = 3
 输出:5
 解释:要想以最大跳跃次数从下标 0 到下标 n - 1 ,可以按下述跳跃序列执行操作:
 - 从下标 0 跳跃到下标 1 。 
 - 从下标 1 跳跃到下标 2 。 
 - 从下标 2 跳跃到下标 3 。 
 - 从下标 3 跳跃到下标 4 。 
 - 从下标 4 跳跃到下标 5 。 
 可以证明,从 0 到 n - 1 的所有方案中,不存在比 5 步更长的跳跃序列。因此,答案是 5 。 

示例 3:

 输入:nums = [1,3,6,4,1,2], target = 0
 输出:-1
 解释:可以证明不存在从 0 到 n - 1 的跳跃序列。因此,答案是 -1 。 

提示:

  • 2 <= nums.length == n <= 1000
  • -109 <= nums[i] <= 109
  • 0 <= target <= 2 * 109
 class Solution {
 public:
     int maximumJumps(vector<int>& nums, int target) {
         int n = nums.size();
         vector<int> dp(n + 1, 0); //到达i的最小步数为dp[i]
         dp[0] = 0;
         for (int i = 1; i < n; i++) {
             for(int j = 0; j < i; j++) {
                 // j为0,或者j可以到达i并且满足target
                 if ((dp[j] != 0 || j == 0) && abs(nums[i] - nums[j]) <= target) {
                     dp[i] = max(dp[i], dp[j] + 1);
                 }
             }
         }
         return dp[n - 1] == 0 ? -1 :dp[n - 1] ;
     }
 };

6912. 构造最长非递减子数组

给你两个下标从 0 开始的整数数组 nums1nums2 ,长度均为 n

让我们定义另一个下标从 0 开始、长度为 n 的整数数组,nums3 。对于范围 [0, n - 1] 的每个下标 i ,你可以将 nums1[i]nums2[i] 的值赋给 nums3[i]

你的任务是使用最优策略为 nums3 赋值,以最大化 nums3最长非递减子数组 的长度。

以整数形式表示并返回 nums3最长非递减 子数组的长度。

注意:子数组 是数组中的一个连续非空元素序列。

示例 1:

 输入:nums1 = [2,3,1], nums2 = [1,2,1]
 输出:2
 解释:构造 nums3 的方法之一是: 
 nums3 = [nums1[0], nums2[1], nums2[2]] => [2,2,1]
 从下标 0 开始到下标 1 结束,形成了一个长度为 2 的非递减子数组 [2,2] 。 
 可以证明 2 是可达到的最大长度。

示例 2:

 输入:nums1 = [1,3,2,1], nums2 = [2,2,3,4]
 输出:4
 解释:构造 nums3 的方法之一是: 
 nums3 = [nums1[0], nums2[1], nums2[2], nums2[3]] => [1,2,3,4]
 整个数组形成了一个长度为 4 的非递减子数组,并且是可达到的最大长度。

示例 3:

 输入:nums1 = [1,1], nums2 = [2,2]
 输出:2
 解释:构造 nums3 的方法之一是: 
 nums3 = [nums1[0], nums1[1]] => [1,1] 
 整个数组形成了一个长度为 2 的非递减子数组,并且是可达到的最大长度。

提示:

  • 1 <= nums1.length == nums2.length == n <= 105
  • 1 <= nums1[i], nums2[i] <= 109
 class Solution {
     public int maxNonDecreasingLength(int[] nums1, int[] nums2) {
         int n = nums1.length;
         if (n == 1) return 1;
         int[][] dp = new int[n][2];
         dp[0][0] = dp[0][1] = 1;
         int ans = 0;
         for (int i = 1; i < n; i++) {
             // 给定一个初值,可以理解为以i处元素结尾的连续子数组的长度为1
             // 这样可以保证在i处元素都小于nums1[i-1]和nums2[i-1]时有默认值
             dp[i][0] = dp[i][1] = 1;
             // 1 当nums1[i] >= nums1[i-1]时,此时以nums1[i]结尾的连续子数组的长度就是以nums1[i-1]结尾的连续子数组长度+1
             if (nums1[i] >= nums1[i-1]) dp[i][0] = Math.max(dp[i][0], dp[i-1][0]+1);
             // 2 当nums1[i] >= nums2[i-1]时,此时以nums1[i]结尾的连续子数组的长度就是以nums2[i-1]结尾的连续子数组长度+1
             if (nums1[i] >= nums2[i-1]) dp[i][0] = Math.max(dp[i][0], dp[i-1][1]+1);
             // 3 当nums2[i] >= nums1[i-1]时,此时以nums2[i]结尾的连续子数组的长度就是以nums1[i-1]结尾的连续子数组长度+1
             if (nums2[i] >= nums1[i-1]) dp[i][1] = Math.max(dp[i][1], dp[i-1][0]+1);
             // 4 当nums2[i] >= nums2[i-1]时,此时以nums2[i]结尾的连续子数组的长度就是以nums2[i-1]结尾的连续子数组长度+1
             if (nums2[i] >= nums2[i-1]) dp[i][1] = Math.max(dp[i][1], dp[i-1][1]+1);
             // 比较连续子数组的最大长度
             ans = Math.max(ans, Math.max(dp[i][0], dp[i][1]));
         }
 ​
         return ans;
     }
 }

6919. 使数组中的所有元素都等于零

给你一个下标从 0 开始的整数数组 nums 和一个正整数 k 。

你可以对数组执行下述操作 任意次 :

从数组中选出长度为 k 的 任一 子数组,并将子数组中每个元素都 减去 1 。 如果你可以使数组中的所有元素都等于 0 ,返回 true ;否则,返回 false 。

子数组 是数组中的一个非空连续元素序列。

示例 1:

输入:nums = [2,2,3,1,1,0], k = 3 输出:true 解释:可以执行下述操作:

  • 选出子数组 [2,2,3] ,执行操作后,数组变为 nums = [1,1,2,1,1,0] 。
  • 选出子数组 [2,1,1] ,执行操作后,数组变为 nums = [1,1,1,0,0,0] 。
  • 选出子数组 [1,1,1] ,执行操作后,数组变为 nums = [0,0,0,0,0,0] 。 示例 2:

输入:nums = [1,3,1,1], k = 2 输出:false 解释:无法使数组中的所有元素等于 0 。

提示:

1 <= k <= nums.length <= 105 0 <= nums[i] <= 106

差分数组

 class Solution {
 public:
     bool checkArray(vector<int> &nums, int k) {
         int n = nums.size(), sum_d = 0;
         vector<int> d(n + 1);
         for (int i = 0; i < n; i++) {
             sum_d += d[i];
             int x = nums[i];
             // x表示当前数值
             x += sum_d;
             // 已经为0不需要操作
             if (x == 0) continue; // 无需操作
             // 如果小于0说明多减 或者 是超过个数
             if (x < 0 || i + k > n) return false; // 无法操作
             // 差分
             sum_d -= x; // 直接加到 sum_d 中,不需要d[i] - x
             d[i + k] += x;
         }
         return true;
     }
 };
 ​