题目描述:
示例 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 <= 105
1 <= nums[i] <= 104
1 <= x <= 109
第一眼看到这道题的时候,首先想到用博弈dp,卡了半天没写出来(我太菜了)
看题解通过反向考虑,判断从nums两头减数字能否等于x, 相当于判断数组nums是否有子数组和恰好等于数组总和sum-x,并求取最大长度。用双指针或者滑动窗口遍历数组计算最长和为sum-x的子数组长度。(哎,自己为什么没想到呢)
最终呈现代码:
int minOperations(vector<int>& nums, int x) {
int n = nums.size();
int sum = 0; //存储所有和
for(int i=0;i<n;i++)
sum+=nums[i];
int maxv = -1,val = sum-x;
int l=0,r=0; //双指针
int cursum = 0;
while(r<n){
cursum += nums[r++];
while(cursum>val&&l<r)
cursum-=nums[l++];
if(cursum==val)
maxv = max(maxv,r-l);
//当相等时,因为上面l++,实际区间是[l-1,r],闭区间,一共有r-(l-1)+1=r-l
}
if(maxv==-1) return -1;
return n-maxv;
}