day115—同向双指针—将x减到0的最小操作数(LeetCode-1658)

题目描述

给你一个整数数组 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 <= 105
  • 1 <= nums[i] <= 104
  • 1 <= x <= 109

解决方案:

核心转换思路

  1. 原本问题:从数组两端 删除元素,使删除的元素和等于 x

  2. 等价问题:找到数组中间一个连续子数组 ,使其和等于 total - x

  3. 这样两端删除的次数最少 = 数组总长度 - 中间子数组长度最大

算法步骤

  1. 计算数组总和 total

  2. 计算中间子数组的目标和:midSum = total - x

  3. 如果 midSum < 0:不可能,返回 -1

  4. 如果 midSum == 0:需要删除所有元素,返回数组长度

  5. 用滑动窗口找和为 midSum最长连续子数组

  6. 如果找到:返回 len - 最长子数组长度

  7. 如果没找到:返回 -1

滑动窗口细节

  • 维护窗口 [left, i]的和为 sum

  • sum > midSum时,从左收缩窗口

  • sum == midSum时,更新最大窗口长度

  • 窗口长度越大,两端删除的元素就越少

时间复杂度:O(n),每个元素最多进出窗口一次

举例

cpp 复制代码
nums = [1,1,4,2,3], x = 5
total = 11, midSum = 6
最长和为6的子数组:[1,1,4],长度=3
最小操作次数 = 5 - 3 = 2
删除两端元素:[2,3]

结果:返回删除两端元素的最少操作次数,如果不可能则返回 -1。

函数源码:

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int len =nums.size();
        int ans=0;
        int left=0;

        int midSum=accumulate(nums.begin(),nums.end(),0) - x;//求和
        if(midSum<0)   return -1;
        if(midSum==0)  return len;

        int sum=0;
        for(int i=0;i<len;i++){
            sum+=nums[i];
            while(sum>midSum){
                sum-=nums[left];
                left+=1;
            }
            if(sum==midSum) ans=max(ans,i-left+1);
        }
        return ans==0? -1:len-ans;
    }

};
相关推荐
全栈工程师修炼指南2 小时前
Nginx | 负载均衡策略:一致性哈希算法实践
运维·算法·nginx·负载均衡·哈希算法
Jerryhut2 小时前
sklearn函数总结六——特征降维 压缩数据 - 特征提取(PCA&LDA)
人工智能·算法·机器学习·scikit-learn·sklearn
apcipot_rain2 小时前
CCF算法能力大赛T3 暴力法 反思
算法
前端小白在前进3 小时前
力扣刷题:有效的括号
算法·leetcode·职场和发展
EXtreme353 小时前
算法深潜:链表中的生死之环(LeetCode 141 & 142 详解)
数据结构·算法·leetcode·链表·快慢指针·数学证明·带环链表
2301_803554523 小时前
Pimpl(Pointer to Implementation)设计模式详解
c++·算法·设计模式
leoufung3 小时前
LeetCode 211:设计添加与搜索单词的数据结构(Trie + DFS)
数据结构·leetcode·深度优先
Dream it possible!3 小时前
LeetCode 面试经典 150_图的广度优先搜索_蛇梯棋(93_909_C++_中等)(广度优选搜索)
c++·leetcode·面试·广度优先
资深web全栈开发3 小时前
LeetCode 3578:统计极差最大为 K 的分割方式数 - 深入浅出指南
算法·leetcode·前缀和·动态规划·滑动窗口