当前位置: 首页 > news >正文

算法设计与分析(十三)

Count of Range Sum

更多技术博客 http://vilins.top/

题目

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.

分析

题目的意思是给出一个数组和一个上界和下界,要求在连续的区间范围求和,使得和在给出的下界和上界的范围内,要求给出满足条件的区间的个数。
首先分析这个问题,这里涉及到区间求和,对于这类题目,一般的套路是算一个O(n)复杂度的连续求和,自然,题目也说到,通过一般的方法可以在O(n*n)的复杂度求出来,但这样显然会超时。
这里我们采用分治算法来算,首先我们理解以下基本事实:
对于两个有序的数组,我们假设其为n1和n2,那么对于n1的一个数,如果我们在n2找到最后下标i1使得n2[i1]<n1[i]并且有最后下标i2使得n2[i2]>n1[i],那么在n2中比n1[i]大的个数为i2-i1。

这里我们采用分治算法用到上述思想,我们不断将整个数组划分成小的问题,在最后一个只有两个元素时开始返回,计算对左边数组的每一个元素,我们利用上述的思想,每处理完一个子问题的时候对其进行归并排序的合并,使得问题的左右两边总是有序的,这样一来不断往上返回,最后得到结果。注意一个问题就是左右两边总是有序的,并且我们注意到左边数组的下标总是小于右边数组的下标,那么得到的范围也必定是从小下标到大的下标。

源码

class Solution { public: void mergeSort(vector<long>& sum, int b, int m, int e) { int n1 = m - b ; int n2 = e - m ; vector<long> left(n1, 0); vector<long> right(n2, 0); for(int i = 0; i < n1; i++) { left[i] = sum[b + i]; } for(int i = 0; i < n2; i++) { right[i] = sum[m + i]; } int i = 0, j= 0; for(int k = b; k < e; k++) { if((left[i] > right[j])) { sum[k] = right[j]; j++; if(j == n2) { for(int q = i; q < n1; q++) { sum[k+1+q-i] = left[q]; } break; } } else { //cout << "k "<< k << endl; sum[k] = left[i]; i++; if(i == n1) { for(int q = j; q < n2; q++) { sum[k+1+q-j] = right[q]; } break; } } } } int merge(vector<long>& sum, int lower, int upper, int low_index, int high_index) { if(high_index - low_index <= 1) { return 0; } int mid = (low_index + high_index)/2; int m = mid, n = mid, count = 0; count = merge(sum, lower, upper, low_index, mid) + merge(sum, lower, upper, mid, high_index); for(int i = low_index; i < mid; i++) { while((sum[m] - sum[i] < lower)&&m < high_index) { m++; } while((sum[n] - sum[i] <= upper)&&n < high_index) { n++; } count += (n - m); } mergeSort(sum, low_index, mid, high_index); //inplace_merge(sum.begin()+low_index, sum.begin()+mid, sum.begin()+high_index); return count; } int countRangeSum(vector<int>& nums, int lower, int upper) { vector<long> sum(nums.size()+1, 0); for(int i = 0; i < nums.size(); i++) { sum[i+1] = sum[i] + nums[i]; } return merge(sum, lower, upper, 0, nums.size()+1); } };

复杂度分析

算法复杂度分析,我们这里是基于递归实现的,排序的时间复杂度为O(n),在求解的时候,递归求解复杂度为logn,加上排序的开销,总的复杂度应该就是O(nlogn),而空间复杂度是用在对数组进行依次求和的存储,复杂度为O(n)。在对左右两个数组合并我用自己实现的函数时,效果会差一些,而用c++标准库的函数的时候,也就是用inplace_merge这个函数,计算起来会快一点点,可能是某些细节的优化问题。

更多技术博客 http://vilins.top/

http://www.jsqmd.com/news/933954/

相关文章:

  • 不止Docker!用Lima在Mac上秒级启动一个带Rosetta的x86 Linux开发环境
  • 差分进化算法原理与工程实践详解
  • 为什么UNet在医学图像分割上这么牛?聊聊小数据、过拟合与‘U型’结构的秘密
  • 告别大屏尴尬!用postcss-mobile-forever给你的移动端页面加个‘安全锁’(Vite/Vue3配置实战)
  • 告别混乱!Android14分区管理避坑指南:从Android.mk迁移到Android.bp时,vendor和odm模块配置的那些坑
  • 不止于配置:用CLion+QT5+CMake打造高效C++ GUI开发工作流(附项目模板)
  • MAX30100血氧心率双参数实时采集与显示Python代码包(含树莓派/ESP32适配)
  • ThinkPad X1 Carbon 指纹识别在 Ubuntu 20.04 上终于能用了!保姆级配置与排错指南
  • 告别启动卡顿!CocosCreator Bundle实战:从resources迁移到自定义AB包(附TypeScript代码)
  • Ubuntu 20.04上搞定Pylith 4.0.0和ParaView 5.12.0:从安装到可视化,一个完整的地球物理模拟环境搭建指南
  • 别再只用JSP了!SpringBoot3搭配Thymeleaf开发企业级后台页面的5个实战技巧
  • 别再乱点Menuconfig了!ESP-IDF项目配置保姆级指南(附VSCode一键启动)
  • API即服务:微创业者的技术新基建与实战指南
  • 物联网项目实战:从传感器到云端的全栈开发指南
  • STM32F103C8T6用HAL库驱动74HC595,3分钟搞定数码管显示(附Proteus仿真文件)
  • 渗透测试手记:如何用Gobuster搭配自定义字典,精准挖出靶场里的‘隐藏关卡’
  • QtCreator新手避坑指南:从安装到第一个UI界面,手把手带你避开那些‘头文件缺失’的坑
  • 基于ESP32与VFD屏制作网络时钟:从硬件连接到NTP同步的完整实践
  • 虚拟现实之父获和平奖:技术伦理与数字时代的人文反思
  • 避坑指南:Node-RED连接ThingsBoard时,MQTT主题、属性、RPC这三大坑怎么填?
  • 留学生论文交稿在即?应对2026年Turnitin检测:英文降AI率实操
  • 用风筝布和碳纤维杆DIY仿生蝴蝶翅膀:从图纸到骨架的保姆级教程
  • 别再死磕官方文档了!用PHPStudy+竹子姐视频,30分钟搞定Geant4第一个粒子模拟
  • 别再只会用timeout了!Windows批处理(bat)的5个隐藏技巧:从窗口美化到模拟黑客屏保
  • Virtualenv实战:从安装到删除,手把手教你管理Django和Flask项目的Python环境
  • 深度解析Awoo Installer:Nintendo Switch游戏安装器的架构设计与实现原理
  • 超越基础发光:在Unity ShaderGraph中制作可旋转、带方向性的高级边缘光效果
  • 用Python+OpenCV+SVM给人民币‘验明正身’:一个图像分类的实战项目(附完整代码)
  • Windows Cleaner:智能自动化C盘清理与系统性能优化完整解决方案
  • SAM模型调参实战:如何用`SamAutomaticMaskGenerator`将分割结果从178个优化到335个?