Leetcode.1658 将 x 减到 0 的最小操作数

题目链接

Leetcode.1658 将 x 减到 0 的最小操作数 rating : 1817

题目描述

给你一个整数数组 n u m s nums nums 和一个整数 x x x 。每一次操作时,你应当移除数组 n u m s nums nums 最左边或最右边的元素,然后从 x x x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x x x 恰好 减到 0 0 0 ,返回 最小操作数 ;否则,返回 − 1 -1 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 ≤ n u m s . l e n g t h ≤ 1 0 5 1 \leq nums.length \leq 10^5 1nums.length105
  • 1 ≤ n u m s [ i ] ≤ 1 0 4 1 \leq nums[i] \leq 10^4 1nums[i]104
  • 1 ≤ x ≤ 1 0 9 1 \leq x \leq 10^9 1x109

解法:滑动窗口

本题要求我们从数组的两端取数,能够用最少的数将x减为0,返回这个最少的次数。
由于正向思考,比较难以处理,所以这里可以逆向思考:数组的和为 s u m sum sum , t a r g e t = s u m − x target = sum - x target=sumx,那么我们就用滑动窗口维护一个和为 target 的最大区间,那么此时数组的长度 n 减去 此时target区间的最大长度 就是我们要求的答案。

Leetcode.1658 将 x 减到 0 的最小操作数_第1张图片
Leetcode.1658 将 x 减到 0 的最小操作数_第2张图片

  • 时间复杂度: O ( n ) O(n) O(n)

C++代码:

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();
        int ans = 1e9;
        int sum = accumulate(nums.begin(),nums.end(),0);
        if(sum < x) return -1;

        sum -= x;
        int m = 0;
        for(int i = 0,j = 0;j < n;j++){
            m += nums[j];
            if(m > sum){
                while(m > sum){
                    m -= nums[i++];
                }
            }
            if(m == sum){
                ans = min(ans,n - (j - i + 1));
            }
        }
        return ans == 1e9 ? -1 : ans;
    }
};

Java代码:

class Solution {
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        int sum = 0;
        for(int e:nums) sum += e;

        int target = sum - x;
        //特判数组的和 sum < x 的情况,这时直接返回 -1
        if(target < 0) return -1;


        int m = 0;
        int len = -1;
        for(int i = 0,j = 0;j < n;j++){
            m += nums[j];
            while(m > target){
                    m -= nums[i++];
                }

             //当区间的和 等于 target时 才更新数组的长度   
            if(m == target){
                len = Math.max(len,j - i + 1);
            }
        }
        return len == -1 ? -1 : n - len;
    }
}

相似题目

Leetcode.3 无重复字符的最长子串
Leetcode.209 长度最小的子数组
Leetcode.713 乘积小于 K 的子数组
Leetcode.2516 每种字符至少取 K 个

你可能感兴趣的:(Leetcode,leetcode,算法)