[LeetCode] 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
), inclusive.
Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.
Example:
Input: nums =[-2,5,-1]
, lower =-2
, upper =2
,
Output: 3
Explanation: The three ranges are :[0,0]
,[2,2]
,[0,2]
and their respective sums are:-2, -1, 2
.
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
这道题给了我们一个数组,又给了一个下限和一个上限,让求有多少个不同的区间使得每个区间的和在给定的上下限之间。这道题的难度系数给的是 Hard,的确是一道难度不小的题,题目中也说了 Brute Force 的方法太 Naive 了,只能另想方法了。To be honest,这题超出了博主的能力范围,所以博主也没挣扎了,直接上网搜大神们的解法啦。首先根据前面的那几道类似题 Range Sum Query - Mutable,Range Sum Query 2D - Immutable 和 Range Sum Query - Immutable 的解法可知类似的区间和的问题一定是要计算累积和数组 sums 的,其中 sum[i] = nums[0] + nums[1] + ... + nums[i],对于某个i来说,只有那些满足 lower <= sum[i] - sum[j] <= upper 的j能形成一个区间 [j, i] 满足题意,目标就是来找到有多少个这样的 j (0 =< j < i) 满足 sum[i] - upper =< sum[j] <= sum[i] - lower,可以用 C++ 中由红黑树实现的 multiset 数据结构可以对其中数据排序,然后用 upperbound 和 lowerbound 来找临界值。lower_bound 是找数组中第一个不小于给定值的数(包括等于情况),而 upper_bound 是找数组中第一个大于给定值的数,那么两者相减,就是j的个数,参见代码如下:
解法一:
class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int res = ;
long long sum = ;
multiset<long long> sums;
sums.insert();
for (int i = ; i < nums.size(); ++i) {
sum += nums[i];
res += distance(sums.lower_bound(sum - upper), sums.upper_bound(sum - lower));
sums.insert(sum);
}
return res;
}
};
我们再来看一种方法,这种方法的思路和前一种一样,只是没有 STL 的 multiset 和 lower_bound 和 upper_bound 函数,而是使用了 Merge Sort 来解,在混合的过程中,已经给左半边 [start, mid) 和右半边 [mid, end) 排序了。当遍历左半边,对于每个i,需要在右半边找出k和j,使其满足:
j是第一个满足 sums[j] - sums[i] > upper 的下标
k是第一个满足 sums[k] - sums[i] >= lower 的下标
那么在 [lower, upper] 之间的区间的个数是 j - k,同时也需要另一个下标t,用来拷贝所有满足 sums[t] < sums[i] 到一个寄存器 Cache 中以完成混合排序的过程,这个步骤是混合排序的精髓所在,实际上这个寄存器的作用就是将 [start, end) 范围内的数字排好序先存到寄存器中,然后再覆盖原数组对应的位置即可,(注意这里 sums 可能会整型溢出,使用长整型 long 代替),参见代码如下:
解法二:
class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
vector<long> sums(nums.size() + , );
for (int i = ; i < nums.size(); ++i) {
sums[i + ] = sums[i] + nums[i];
}
return countAndMergeSort(sums, , sums.size(), lower, upper);
}
int countAndMergeSort(vector<long>& sums, int start, int end, int lower, int upper) {
if (end - start <= ) return ;
int mid = start + (end - start) / ;
int cnt = countAndMergeSort(sums, start, mid, lower, upper) + countAndMergeSort(sums, mid, end, lower, upper);
int j = mid, k = mid, t = mid;
vector<int> cache(end - start, );
for (int i = start, r = ; i < mid; ++i, ++r) {
while (k < end && sums[k] - sums[i] < lower) ++k;
while (j < end && sums[j] - sums[i] <= upper) ++j;
while (t < end && sums[t] < sums[i]) cache[r++] = sums[t++];
cache[r] = sums[i];
cnt += j - k;
}
copy(cache.begin(), cache.begin() + t - start, sums.begin() + start);
return cnt;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/327
类似题目:
Range Sum Query 2D - Immutable
Count of Smaller Numbers After Self
参考资料:
https://leetcode.com/problems/count-of-range-sum/
https://leetcode.com/problems/count-of-range-sum/discuss/77990/Share-my-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Count of Range Sum 区间和计数的更多相关文章
- [LeetCode] 327. Count of Range Sum 区间和计数
Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...
- 327 Count of Range Sum 区间和计数
Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...
- LeetCode Count of Range Sum
原题链接在这里:https://leetcode.com/problems/count-of-range-sum/ 题目: Given an integer array nums, return th ...
- 【算法之美】你可能想不到的归并排序的神奇应用 — leetcode 327. Count of Range Sum
又是一道有意思的题目,Count of Range Sum.(PS:leetcode 我已经做了 190 道,欢迎围观全部题解 https://github.com/hanzichi/leetcode ...
- 327. Count of Range Sum
/* * 327. Count of Range Sum * 2016-7-8 by Mingyang */ public int countRangeSum(int[] nums, int lowe ...
- [Swift]LeetCode327. 区间和的个数 | Count of Range Sum
Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...
- leetcode@ [327] Count of Range Sum (Binary Search)
https://leetcode.com/problems/count-of-range-sum/ Given an integer array nums, return the number of ...
- 【LeetCode】327. Count of Range Sum
题目: Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusiv ...
- leetcode327 Count of Range Sum
问题描述: 给定一个整数数组nums,返回其所有落在[low, upper]范围内(包含边界)的区间和的数目. 区间和sums(i, j)的定义为所有下标为i到j之间(i ≤ j)的元素的和,包含边界 ...
随机推荐
- Js ==和===的区别
===判断: Undefined === Undefined,返回 true Null === Null,返回 true null == undefined,返回 false NaN === NaN, ...
- 跨域之URL
在介绍怎么跨域之前,先来弄清楚一个概念:URL.以下内容摘自维基百科. 统一资源定位符(或称统一资源定位器/定位地址.URL地址等,英语:Uniform / Universal Resource Lo ...
- PHP实现查询Memcache内存中的所有键与值
使用Memcache时,我们可以用memcache提供的get方法,通过键查询到当前的数据,但是有时候需要查询内存中所有的键和值,这个时候可以使用下面的代码实现: <?php /** * Cre ...
- Node基础篇(概要)
Node简介 客户端的JavaScript是怎样的 什么是 JavaScript? 脚本语言 运行在浏览器中 一般用来做客户端页面的交互(Interactive) JavaScript 的运行环境? ...
- Redis简单案例(一) 网站搜索的热搜词
对于一个网站来说,无论是商城网站还是门户网站,搜索框都是有一个比较重要的地位,它的存在可以说是 为了让用户更快.更方便的去找到自己想要的东西.对于经常逛这个网站的用户,当然也会想知道在这里比较“火” ...
- Linux下Weblogic创建域方法和步骤
Weblogic 创建域 以weblogic帐号登录(与创建域目录相对应账户) cd /home/weblogic/bea/weblogic92/common/bin 执行./config.sh进入配 ...
- Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池
连接池原理 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接池 ...
- Eclipse Maven Spring MyBatis 配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- ipad和iphone的适配
关于xib或者storybord下iphone的横竖屏的适配以及ipad的适配 ios8出现了Size Classes,解决了各种屏幕适配的问题,他把屏幕的宽和高分别分成了三种,把屏幕总共分成了九种情 ...
- CALayer的m34 - 三维透视效果
CATransform3D transform = CATransform3DIdentity; // 修改transform的m34达到透视效果 // - 1.0 / (500 ~ 1000 效果最 ...