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;
    }

};
相关推荐
永远都不秃头的程序员(互关)19 分钟前
【K-Means深度探索(三)】告别“初始陷阱”:K-Means++优化质心初始化全解析!
算法·机器学习·kmeans
程序员-King.22 分钟前
day136—快慢指针—重排链表(LeetCode-143)
算法·leetcode·链表·快慢指针
万行23 分钟前
差速两轮机器人位移与航向角增量计算
人工智能·python·算法·机器人
qq_3363139323 分钟前
java基础-多线程练习
java·开发语言·算法
不知名XL24 分钟前
day25 贪心算法 part03
算法·贪心算法
期待のcode36 分钟前
Java虚拟机的垃圾回收器
java·开发语言·jvm·算法
星火开发设计39 分钟前
C++ 分支结构:if-else 与 switch-case 的用法与区别
开发语言·c++·学习·算法·switch·知识·分支
txzrxz41 分钟前
数据结构有关的题目(栈,队列,set和map)
数据结构·c++·笔记·算法··队列
CoderCodingNo1 小时前
【GESP】C++五级练习题(前缀和) luogu-P1114 “非常男女”计划
数据结构·c++·算法
知乎的哥廷根数学学派1 小时前
基于卷积特征提取和液态神经网络的航空发动机剩余使用寿命预测算法(python)
人工智能·pytorch·python·深度学习·神经网络·算法