【滑动窗口】将X减到0的最小操作数
将X减到0的最小操作数
1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)
文章目录
- 将X减到0的最小操作数
- 题目描述
- 算法原理
- 代码编写
- Java代码编写
- C++代码编写
题目描述
给你一个整数数组 nums
和一个整数 x
。每一次操作时,你应当移除数组 nums
最左边或最右边的元素,然后从 x
中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。
如果可以将 x
恰好 减到 0
,返回 最小操作数 ;否则,返回 -1
。
示例 1:
输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。
示例 2:
输入:nums = [5,6,7,8,9], x = 4
输出:-1
示例 3:
输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^4
1 <= x <= 10^9
算法原理
这道题直接上手写代码还是有一定难度的,于是正难则反,我们可以使用以下的策略:
转化:找出最长的子数组的长度,所有元素的和刚好等于
sum - x
转化问题:求
target = sum - x
,如果target < 0
,问题无解
sum
一开始就遍历数组然后存入数组元素的总和初始化左右指针
left、right
,定义一个tmp
存入right
走过数组的和在
right < 数组长度
的时候,一直循环
tmp < target right ++
tmp > target left ++
,然后tmp
的值也就与之需要--
- 如果满足
tmp == target
,那就更新结果注意最后结果的返回是需要数组长度 -
ret
这里有一个细节问题:
题目中已经有规定了
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^4
1 <= x <= 10^9
数组中的元素应该是
>= 1
,如果没有的话,数组元素中出现了负数,那么这道题的规律也就不复存在,此时我们可能需要别的算法来解决。
代码编写
Java代码编写
class Solution {
public int minOperations(int[] nums, int x) {
int sum = 0;
// 存入nums所有的和
for(int a : nums) sum += a;
// 正难则反
int target = sum - x;
// 处理细节
if(target < 0) return -1;
// 结果
int ret = -1;
for(int left = 0, right = 0, tmp = 0; right < nums.length; right++ )
{
// tmp 也就是 right 指针遍历的和
tmp += nums[right]; // 进窗口
while(tmp > target) // 判断
tmp -= nums[left++]; // 出窗口
if(tmp == target)
ret = Math.max(ret, right - left + 1);
}
if(ret == -1) return ret;
else return nums.length - ret;
}
}
C++代码编写
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int sum = 0;
for(int a: nums) sum += a;
int target = sum - x;
// 处理细节问腿
if(target < 0) return -1;
int ret = -1;
for(int left = 0, right = 0, tmp = 0; right < nums.size(); right ++)
{
tmp += nums[right]; // 进窗口
while(tmp > target)
tmp -= nums[left++]; // 出窗口
if(tmp == target) // 更新结果
ret = max(ret, right - left + 1);
}
if(ret == -1) return ret;
else return nums.size() -ret;
}
};