自学内容网 自学内容网

力扣1477. 找两个和为目标值且不重叠的子数组

力扣1477. 找两个和为目标值且不重叠的子数组

题目解析及思路

题目要求找到两个互不重叠的子数组和都等于target的子数组长度和的最小值

暴力思路(差不多nlogn):将所有子数组和等于target的子数组用map存起来下标

  • 双指针枚举,如果有重叠就跳过,直到找到符合要求的就是最小值

代码

class Solution {
public:
    int minSumOfLengths(vector<int>& arr, int target) {
        //如果整个数组的和都比2倍target小,说明不可能分成两部分
        if(accumulate(arr.begin(),arr.end(),0LL) < target * 2) 
            return -1;
        //multimap可以存多个相同键值的对组,并且默认升序排列
        multimap<int,int> res;
        int l = 0,r = 0,sum = 0;
        //双指针求子数组和,把所有符合要求的子数组的{长度,下标}存入表中
        while(r < arr.size())
        {
            sum += arr[r];
            r ++;
            if(sum < target) continue;
            while(sum > target)
            {
                sum -= arr[l];
                l ++;
            }
            if(sum == target)
                res.insert({r-l,l});
        }
        int ans = INT_MAX;
        //枚举表中数据
        for(auto r1 = res.begin();r1 != res.end();r1 ++)
        {
            //剪枝,因为multimap默认升序,因此r1->first <= r2->first
            if(r1->first * 2 >= ans) break;
            auto r2 = r1;
            while((++r2) != res.end())
            {
                //判断是否有重叠
                if (r1->second < r2->second && r1->second + r1->first > r2->second) continue;
                if (r2->second < r1->second && r2->second + r2->first > r1->second) continue;
                //如果没重叠,当前答案一定是最优解(两个都是最小)
                ans = min(ans,r1->first+r2->first);
                break;
            }
        }
        return ans == INT_MAX ? -1 : ans;
    }
};

原文地址:https://blog.csdn.net/Pisasama/article/details/142870635

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!