前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >LeetCode 1712. 将数组分成三个子数组的方案数(前缀和 + 二分查找)

LeetCode 1712. 将数组分成三个子数组的方案数(前缀和 + 二分查找)

作者头像
Michael阿明
发布2021-02-19 14:40:57
发布2021-02-19 14:40:57
85100
代码可运行
举报
运行总次数:0
代码可运行

文章目录

221 / 3117,前7.1%

574 / 9692,前 5.9%

周赛前2题如下:

LeetCode 5641. 卡车上的最大单元数(排序,模拟)

LeetCode 5642. 大餐计数(map计数 + 二分查找)

第4题:LeetCode 5644. 得到子序列的最少操作次数(最长上升子序DP nlogn)

1. 题目

我们称一个分割整数数组的方案是 好的 ,当它满足:

  • 数组被分成三个 非空 连续子数组,从左至右分别命名为 left , mid , right 。
  • left 中元素和小于等于 mid 中元素和,mid 中元素和小于等于 right 中元素和。

给你一个 非负 整数数组 nums ,请你返回 好的 分割 nums 方案数目

由于答案可能会很大,请你将结果对 109 + 7 取余后返回。

代码语言:javascript
代码运行次数:0
复制
示例 1:
输入:nums = [1,1,1]
输出:1
解释:唯一一种好的分割方案是将 nums 分成 [1] [1] [1] 。

示例 2:
输入:nums = [1,2,2,2,5,0]
输出:3
解释:nums 总共有 3 种好的分割方案:
[1] [2] [2,2,5,0]
[1] [2,2] [2,5,0]
[1,2] [2,2] [5,0]

示例 3:
输入:nums = [3,2,1]
输出:0
解释:没有好的分割方案。
 
提示:
3 <= nums.length <= 10^5
0 <= nums[i] <= 10^4

https://leetcode-cn.com/problems/ways-to-split-array-into-three-subarrays/

2. 解题

  • 二分查找前缀和的切分位置
代码语言:javascript
代码运行次数:0
复制
class Solution {
public:
    int waysToSplit(vector<int>& nums) {
        int n = nums.size();
        vector<int> presum(nums);
        for(int i = 1; i < n; i++)
            presum[i] += presum[i-1];//前缀和
        long long ans = 0, mod = 1e9+7;
        for(int i = 0; i < n-2; i++)
        {
            int a = presum[i];
            auto it = lower_bound(presum, i+1, n-2, 2*a);
            //第二段的前缀和至少为 2a, 在 位置 [i+1, n-2] 内查找 
            if(it == -1)
                break;
            // b = presum[it]-a,  c = presum[n-1]-presum[it]
            // c >= b,  presum[it] <= (presum[n-1]+a)/2
            auto it1 = upper_bound(presum, i+1, n-2, (presum[n-1]+a)/2);
            if(it1 != -1 && it1>=it)
                ans = (ans+it1-it+1)%mod;
        }
        return ans;
    }
    int lower_bound(vector<int>& presum, int L, int R, int t)
    {
        int l = L, r = R, n = presum.size(), mid;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(presum[mid] < t)
                l = mid + 1;
            else
            {
                if(mid==L || (presum[mid-1] < t))
                    return mid;
                else
                    r = mid - 1;
            }
        }
        return -1;
    }
    int upper_bound(vector<int>& presum,  int L, int R, int t)
    {
        int l = L, r = R, n = presum.size(), mid;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(presum[mid] > t)
                r = mid - 1;
            else
            {
                if(mid==R || (presum[mid+1] > t))
                    return mid;
                else
                    l = mid + 1;
            }
        }
        return -1;
    }
};

368 ms 83.4 MB C++


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/01/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档