【LeetCode】327. Count of Range Sum

题目:

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.

Range sum S(i, j) is defined as the sum of the elements in nums between indices i and  j (ij), inclusive.

Note:

A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:

Given nums = [-2, 5, -1], lower = -2, upper = 2, Return 3. The three ranges are : [0, 0], [2, 2], [0, 2] and their respective sums are: -2, -1, 2.

提示:

这道题最直观的一个想法就是枚举出所有的子数组,然后检查他们是否在要求的取值范围内,这种方法的时间复杂度是O(n^2)的,显然会超时。

看到这种题目最容易想到的是什么呢?Two Pointers!对,但是在这道题上仅仅使用Two Pointers肯定是不够的,在Two Pointers的思想基础上,融合归并排序,就能找到一个比较好的解决方案。

这里我们的排序对象是前缀求和数组,在归并排序的合并阶段,我们有左数组和右数组,且左和右数组都是排好序的,所以我们可以用i遍历左数组,j,k两个指针分别取在右数组搜索,使得:

  • sums[j] - sums[i] < upper
  • sums[k] - sums[i] >= lower

那么此时,我们就找到了j-k个符合要求的子数组。

由于左右数组都是排好序的,所以当i递增之后,j和k的位置不用从头开始扫描。

最后还有一点需要注意的就是,为了防止溢出,我们的vector容纳的是long long型元素。

代码:

class Solution {
public:
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        int n = nums.size();
        if (n <= 0) {
            return 0;
        }
        vector<long long> sums(n + 1, 0);
        for (int i = 0; i < n; ++i) {
            sums[i+1] = sums[i] + nums[i];
        }
        return merge(sums, 0, n, lower, upper);
    }

    int merge(vector<long long>& sums, int start, int end, int lower, int upper) {
        if (start >= end) {
            return 0;
        }
        int mid = start + (end - start) / 2;
        int count = merge(sums, start, mid, lower, upper) + merge(sums, mid + 1, end, lower, upper);
        vector<long long> tmp(end - start + 1, 0);
        int j = mid + 1, k = mid + 1, t = mid + 1, i = start, r = 0;
        for (; i <= mid; ++i, ++r) {
            while (j <= end && sums[j] - sums[i] <= upper) ++j;
            while (k <= end && sums[k] - sums[i] < lower) ++k;
            count += j - k;
            while (t <= end && sums[t] <= sums[i]) tmp[r++] = sums[t++];
            tmp[r] = sums[i];
        }
        for (int i = 0; i < r; ++i) {
            sums[start + i] = tmp[i];
        }
        return count;
    }
};
时间: 2024-08-07 10:07:34

【LeetCode】327. Count of Range Sum的相关文章

327. Count of Range Sum

/* * 327. Count of Range Sum * 2016-7-8 by Mingyang */ public int countRangeSum(int[] nums, int lower, int upper) { int n = nums.length; long[] sums = new long[n + 1]; for (int i = 0; i < n; ++i) sums[i + 1] = sums[i] + nums[i]; return countWhileMerg

[email&#160;protected] [327] Count of Range Sum (Binary Search)

https://leetcode.com/problems/count-of-range-sum/ Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive. Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), incl

【LeetCode】Binary Tree Maximum Path Sum 解题报告

[题目] Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. For example: Given the below binary tree, 1 / 2 3 Return 6. [解析] 题意:在二叉树中找一条路径,使得该路径的和最大.该路径可以从二叉树任何结点开始,也可以到任何结点结束. 思路:递归求一条经过root的最大路径,这条路径可能是:

LeetCode 327. Count of Range Sum

无意看到的LeetCode新题,不算太简单,大意是给一个数组,询问多少区间和在某个[L,R]之内.首先做出前缀和,将问题转为数组中多少A[j]-A[i] (j>i)在范围内. 有一种基于归并排序的做法,在每次归并完左右两个子区间后,当前区间两部分分别都已经排序完毕,基于有序这一点,扫描后半段区间,对于每个A[i] (i>=mid),目标区间即为[ A[i]-R, A[i]-L ], 对于有序数组来说,求出元素落在某一区间的个数直接就是upper_bound-lower_bound,事实上,这里

【leetcode】357. Count Numbers with Unique Digits

题目描述: Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. 解题分析: 题目要就就是找出 0≤ x < 10n中各位数字都不相同的数的个数.要接触这道题只需要理解: 1.设f(n)表示n为数字中各位都不相同的个数,则有countNumbersWithUniqueDigits(n)=f(1)+f(2)+……+f(n)=f(n)+countNumbersWithU

【leetcode】1289. Minimum Falling Path Sum II

题目如下: Given a square grid of integers arr, a falling path with non-zero shifts is a choice of exactly one element from each row of arr, such that no two elements chosen in adjacent rows are in the same column. Return the minimum sum of a falling path

【leetcode】204 - Count Primes

Description:Count the number of prime numbers less than a non-negative number, n. Hint: Let's start with a isPrime function. To determine if a number is prime, we need to check if it is not divisible by any number less than n. The runtime complexity

【LeetCode】Search for a Range

Search for a Range Given a sorted array of integers, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1]. For ex

【leetcode】Binary Tree Maximum Path Sum (medium)

Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. 找树的最大路径和 注意路径可以从任意点起始和结束. 我发现我真的还挺擅长树的题目的,递归不难.就是因为有个需要比较的量(最大和),所以需要再写一个函数. 因为路径可以从任意点起始和结束,所以每次递归的时候左右子树小于等于0的就可以不管了. #include <iostream> #include