leetcode 1477. 找两个和为目标值且不重叠的子数组 中等

给你一个整数数组 arr 和一个整数值 target 。

请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target 。可能会有多种方案,请你返回满足要求的两个子数组长度和的 最小值 。

请返回满足要求的最小长度和,如果无法找到这样的两个子数组,请返回 -1 。

示例 1:

复制代码
输入:arr = [3,2,2,4,3], target = 3
输出:2
解释:只有两个子数组和为 3 ([3] 和 [3])。它们的长度和为 2 。

示例 2:

复制代码
输入:arr = [7,3,4,7], target = 7
输出:2
解释:尽管我们有 3 个互不重叠的子数组和为 7 ([7], [3,4] 和 [7]),但我们会选择第一个和第三个子数组,因为它们的长度和 2 是最小值。

示例 3:

复制代码
输入:arr = [4,3,2,6,2,3,4], target = 6
输出:-1
解释:我们只有一个和为 6 的子数组。

示例 4:

复制代码
输入:arr = [5,5,4,4,5], target = 3
输出:-1
解释:我们无法找到和为 3 的子数组。

示例 5:

复制代码
输入:arr = [3,1,1,1,5,1,2,1], target = 3
输出:3
解释:注意子数组 [1,2] 和 [2,1] 不能成为一个方案因为它们重叠了。

提示:

  • 1 <= arr.length <= 10^5
  • 1 <= arr[i] <= 1000
  • 1 <= target <= 10^8

分析:首先从右往左,用滑动窗口处理出所有和等于 target 的子数组,用一个数组,记录这些子数组的长度与左端点。接着从左往右,枚举第一个子数组的右端点 r,当一个子数组和恰好等于 target 时,用二分查找之前预处理出来的数组中,那些左端点大于 r 的子数组的最小长度。这里二分查找是查找左端点。这样从左往右枚举完所有的子数组,返回最小长度和即可。

cpp 复制代码
class Solution {
public:
    int minSumOfLengths(vector<int>& arr, int target) {
        int n=arr.size(),ans=INT_MAX;
        vector<pair<int,int>>pos;
        for(int i=n-1,l=i,sum=0,len=INT_MAX;i>=0;--i)
        {
            sum+=arr[i];
            while(sum>target)sum-=arr[l--];
            if(sum==target)len=min(len,l-i+1),pos.push_back({i,len});
        }
        int m=pos.size();
        if(m<2)return -1;

        for(int i=0,l=i,sum=0,len_left=INT_MAX;i<n;++i)
        {
            sum+=arr[i];
            while(sum>target)sum-=arr[l++];
            if(sum==target)
            {
                len_left=i-l+1;
                int left=0,right=m,mid;
                while(left<right)
                {
                    mid=(left+right)/2;
                    if(pos[mid].first<=i)right=mid;
                    else ans=min(ans,len_left+pos[mid].second),left=mid+1;
                }
            }
        }
        if(ans==INT_MAX)return -1;
        return ans;
    }
};
相关推荐
j7~13 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
Shaoshing14 小时前
LeetCode100 42.接雨水
java·算法·leetcode
文丑颜不良啊15 小时前
LeetCode1261~1280题目解析
java·leetcode
Shaoshing16 小时前
LeetCode100 11. 盛最多水的容器
算法·leetcode
海绵宝宝转agent17 小时前
Leetcode二叉树算法个人理解
笔记·学习·算法·leetcode·深度优先
Rain的Java大神之路17 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试
重生之小比特19 小时前
【算法拾光】前缀和|连续的子数组和 + 和相同的二元子数组
算法·leetcode·哈希算法
Pniubi19 小时前
力扣 102二叉树的层序遍历(广度优先搜索)
leetcode·宽度优先
一去不复返的通信er19 小时前
力扣15:盛最多水的容器
算法·leetcode
Navigator_Z19 小时前
LeetCode //C - 1309. Decrypt String from Alphabet to Integer Mapping
c语言·算法·leetcode