C++前缀和算法的应用:统计中位数为 K 的子数组

简介: C++前缀和算法的应用:统计中位数为 K 的子数组

本文涉及的基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频

题目

给你一个长度为 n 的数组 nums ,该数组由从 1 到 n 的 不同 整数组成。另给你一个正整数 k 。

统计并返回 nums 中的 中位数 等于 k 的非空子数组的数目。

注意:

数组的中位数是按 递增 顺序排列后位于 中间 的那个元素,如果数组长度为偶数,则中位数是位于中间靠 左 的那个元素。

例如,[2,3,1,4] 的中位数是 2 ,[8,4,3,5,1] 的中位数是 4 。

子数组是数组中的一个连续部分。

示例 1:

输入:nums = [3,2,1,4,5], k = 4

输出:3

解释:中位数等于 4 的子数组有:[4]、[4,5] 和 [1,4,5] 。

示例 2:

输入:nums = [2,3,1], k = 3

输出:1

解释:[3] 是唯一一个中位数等于 3 的子数组。

参数范围

n == nums.length

1 <= n <= 105

1 <= nums[i], k <= n

nums 中的整数互不相同

分析

变量解释

vSum[i] 记录nums[0,i)中小于k的数量
mLeftOdd left为奇数的:l - 2*vSum[l]
mLeftEven left为偶数的:l - 2*vSum[l]
mLenOdd 长度为奇数的:l - 2*vSum[l]
mLenEven 长度为偶数的:l - 2*vSum[l]

奇偶性

left为奇数 r为奇数 长度为奇数
left为奇数 r为偶数 长度为偶数
left为偶数 r为奇数 长度为偶数
left为偶数 r为偶数 长度为奇数

原理

假定nums[kIndex]等于k,则包括k的子数组可以表示为:nums[left,right],left的取值范围为(-1,kIndex],right的取值范围为[kIndex,m_c)。

nums[l,r]的长度: r-l+1。
nums[l,r]中小于k的数量: vSum[r+1]-vSum[l]。
如果长度是奇数:(长度-1)/2== k的数量 则符合要求 => r-l = 2*(vSum[r+1]-vSum[l])
如果长度是偶数:(长度-2)/2 == k的数量 则符合要求 => r-l-1 = 2*(vSum[r+1]-vSum[l])
将l相关移到右边:r - 2vSum[r+1] = l - 2vSum[l]; r - 2vSum[r+1]-1 = l - 2vSum[l]

代码

核心代码

class Solution {
public:
int countSubarrays(vector& nums, const int k) {
m_c = nums.size();
vector vSum = { 0 };//Vsum[i]记录nums[0,i)中小于k的数量
for (const auto& n : nums)
{
vSum.emplace_back(vSum.back() + (n < k));
}
unordered_map<int, int> mLeftEven, mLeftOdd;
int left = 0;
for (; left < m_c; left++)
{
auto& m = (left & 1) ? mLeftOdd : mLeftEven;
m[left - 2 * vSum[left]]++;
if (k == nums[left])
{
break;
}
}
int iRet = 0;
for (int r = left; r < m_c; r++)
{
const int tmp = r - 2 * vSum[r + 1];
auto& mLenOdd = (r & 1) ? mLeftOdd : mLeftEven;
auto& mLenEven = (r & 1) ? mLeftEven : mLeftOdd;
iRet += mLenOdd[tmp] + mLenEven[tmp - 1];
std::cout << “r:” << r << " 奇数:" << mLenOdd.count(tmp) << " 偶数:" << mLenEven.count(tmp - 1) << std::endl;
}
return iRet;
}
int m_c;
};

测试用例

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
assert(v1[i] == v2[i]);
}
}
template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
int main()
{
Solution slu;
vector nums;
int res;
nums = { 5,11,4,6,2,7,10,8,1,3,9,12 };
res = slu.countSubarrays(nums, 6);
Assert(22, res);
nums = { 2,3,1 };
res = slu.countSubarrays(nums, 3);
Assert(1, res);
nums = { 3,2,1,4,5 };
res = slu.countSubarrays(nums, 4);
Assert(3, res);
//CConsole::Out(res);

}

2023年4月版

class Solution {
public:
int countSubarrays(vector& nums, int k) {
m_c = nums.size();
//大于K的数减小于K
std::unordered_map<int, int> mSubNum;
mSubNum[0] = 1;
int i = 0;
int iGreate = 0, iLess = 0;
for (; (i < m_c)&&( nums[i] != k ) ; i++)
{
iGreate += nums[i] > k;
iLess += nums[i] < k;
mSubNum[iGreate - iLess]++;
}
int iRet = 0;
for (; i < m_c; i++)
{
iGreate += nums[i] > k;
iLess += nums[i] < k;
iRet += mSubNum[iGreate - iLess];
iRet += mSubNum[iGreate - iLess-1];
}
return iRet;
}
int m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

| 充满正能量得对大家说

|

|-|

|闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。|

| 墨家名称的来源:有所得以墨记之。 |

|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17


相关文章
|
2天前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
10 3
|
6天前
|
算法 调度
贪心算法基本概念与应用场景
尽管贪心算法在许多问题中都非常有效,但它并不总是会产生最优解。因此,在应用贪心算法前,重要的是先分析问题是否适合采用贪心策略。一些问题可能需要通过动态规划或回溯等其他算法来解决,以找到确切的全局最优解。
22 1
WK
|
9天前
|
机器学习/深度学习 算法 数据挖掘
PSO算法的应用场景有哪些
粒子群优化算法(PSO)因其实现简单、高效灵活,在众多领域广泛应用。其主要场景包括:神经网络训练、工程设计、电力系统经济调度与配电网络重构、数据挖掘中的聚类与分类、控制工程中的参数整定、机器人路径规划、图像处理、生物信息学及物流配送和交通管理等。PSO能处理复杂优化问题,快速找到全局最优解或近似解,展现出强大的应用潜力。
WK
16 1
|
18天前
|
机器学习/深度学习 算法 Python
群智能算法:深入解读人工水母算法:原理、实现与应用
近年来,受自然界生物行为启发的优化算法备受关注。人工水母算法(AJSA)模拟水母在海洋中寻找食物的行为,是一种新颖的优化技术。本文详细解读其原理及实现步骤,并提供代码示例,帮助读者理解这一算法。在多模态、非线性优化问题中,AJSA表现出色,具有广泛应用前景。
|
25天前
|
机器学习/深度学习 算法 数据挖掘
R语言中的支持向量机(SVM)与K最近邻(KNN)算法实现与应用
【9月更文挑战第2天】无论是支持向量机还是K最近邻算法,都是机器学习中非常重要的分类算法。它们在R语言中的实现相对简单,但各有其优缺点和适用场景。在实际应用中,应根据数据的特性、任务的需求以及计算资源的限制来选择合适的算法。通过不断地实践和探索,我们可以更好地掌握这些算法并应用到实际的数据分析和机器学习任务中。
|
30天前
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
1月前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
72 1
|
1月前
|
存储 算法 C++
C++ STL应用宝典:高效处理数据的艺术与实战技巧大揭秘!
【8月更文挑战第22天】C++ STL(标准模板库)是一组高效的数据结构与算法集合,极大提升编程效率与代码可读性。它包括容器、迭代器、算法等组件。例如,统计文本中单词频率可用`std::map`和`std::ifstream`实现;对数据排序及找极值则可通过`std::vector`结合`std::sort`、`std::min/max_element`完成;而快速查找字符串则适合使用`std::set`配合其内置的`find`方法。这些示例展示了STL的强大功能,有助于编写简洁高效的代码。
33 2
|
22天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
22天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。