C++ 中数组中每个元素的超越计数器2025 年 5 月 19 日 | 阅读 13 分钟 算法问题解决中的一个基本问题是超越计数(surpasser count),它衡量数组元素之间的相对顺序。它计算数组中每个元素右侧严格大于该元素的元素数量。当我们需要分析数据集中元素的相对重要性时,尤其是在数据分析、排名系统、竞争性编程等领域,它非常有价值。 其次,计算超越计数问题既具有教育意义又具有实践意义。在教育方面,它教授或更确切地说,向学生和程序员介绍了数组遍历、比较和数据结构以提高计算效率。它可以实际应用于各种领域,从股票价格分析到通过计算在给定股票之后表现更好的股票数量来识别未来趋势。 对于大型数据集,存在一个朴素的 O(n^2) 解决方案,其中每个元素都与数组中所有后续元素进行比较,但这非常耗时。因此,可以通过高级技术来解决这种低效率,例如分治法和 Fenwick 树(二叉索引树)。为了将此解决方案扩展到更大的数组,我们优化了这些技术的计算,使其运行时间为 O(nlogn)。 学习和解决超越计数问题是扩展我们对算法和数据结构理解的机会,并且应该是一个明智选择有助于高效计算的工具的场合。这个问题是可以通过巧妙的技术和周到的设计来优化复杂性的一个绝佳示例。 方法 1:暴力方法计算超越计数的朴素方法是最简单、最直接的方法。这种方法定义了有多少元素大于它右侧的所有元素。它使用两个嵌套循环,外层循环固定在一个元素上,内层循环遍历剩余元素来计算更大的元素。 这种方法的时间复杂度将是 O(n^2),因为外层循环需要 n 次迭代,而内层循环对于每个元素最多需要 n-1 次迭代。它易于理解和实现,但由于其 O(n^2) 的运行时间,它只能用于小型数据集。假设我们才刚刚开始接触基本问题。在这种情况下,朴素法是一种理想的方法,如果我们采用分治法或 Fenwick 树等更优化的方法,朴素法不适用于性能关键型应用程序。 示例让我们通过一个例子来说明使用朴素方法在 C++ 中计算数组中每个元素的超越计数。 输出 Surpasser Count Calculator This program calculates the surpasser count for each element in an array using the brute force approach. --------------------------------------------- Enter the number of elements in the array: 5 Enter the elements of the array: Element 1: 23 Element 2: 45 Element 3: 42 Element 4: 67 Element 5: 59 Input array successfully read! Input Array: 23 45 42 67 59 Now calculating surpasser counts... Calculating surpasser counts step-by-step: Element at index 0 (23): Comparing 23 with 45... Surpasser found! Comparing 23 with 42... Surpasser found! Comparing 23 with 67... Surpasser found! Comparing 23 with 59... Surpasser found! Total surpassers for 23: 4 Element at index 1 (45): Comparing 45 with 42... Not a surpasser. Comparing 45 with 67... Surpasser found! Comparing 45 with 59... Surpasser found! Total surpassers for 45: 2 Element at index 2 (42): Comparing 42 with 67... Surpasser found! Comparing 42 with 59... Surpasser found! Total surpassers for 42: 2 Element at index 3 (67): Comparing 67 with 59... Not a surpasser. Total surpassers for 67: 0 Element at index 4 (59): Total surpassers for 59: 0 Surpasser counts calculated successfully! Final Results: Index Element Surpasser Count ---------------------------------------- 0 23 4 1 45 2 2 42 2 3 67 0 4 59 0 Thank you for using the Surpasser Count Calculator! 说明
复杂度分析时间复杂度 可以通过检查用于计算每个元素的超越计数的循环来分析代码中采用的朴素方法。
因此,朴素法的复杂度为 O(n²)。对于每个元素,它是二次方的,因为我们对数组中它后面的所有元素进行线性次数的比较。 空间复杂度 除了输入数组,额外使用的空间决定了程序的空间复杂度。
因此,用于存储 surpasserCount 数组的空间复杂度由 O(n) 决定。 方法二:Fenwick 树方法Fenwick 树(也称为二叉索引树)是一种用于对累积频率表执行操作的数据结构。它允许 O(log n) 时间的更新和查询操作。在超越计数问题(我们想计算每个元素右侧有多少元素大于它)中,Fenwick 树用于在从右向左遍历数组时有效地跟踪元素。 通过使用坐标压缩技术,我们将数组元素拟合到与 Fenwick 树使用的 1 基索引兼容的空间中。对于每个元素,我们查询树以了解迄今为止遇到了多少个较大的元素,然后将当前元素添加到树中。这给了我们一个 O(n log n) 的时间复杂度解决方案,运行速度比朴素解决方案快得多。 示例让我们通过一个例子来说明使用 Fenwick 树方法在 C++ 中计算数组中每个元素的超越计数。 输出 Enter the number of elements in the array: 5 Enter the elements of the array: Element 1: 34 Element 2: 45 Element 3: 56 Element 4: 67 Element 5: 78 Input Array: 34 45 56 67 78 Final Results: Element | Surpasser Count ------------------------- 34 | 4 45 | 3 56 | 2 67 | 1 78 | 0 End of Program 说明1. Fenwick 树(二叉索引树)类 FenwickTree 类是解决方案的核心,它提供了两个基本操作:
由于其结构,Fenwick 树非常适合需要快速累积和查询的此类问题,其更新和查询时间均为 O(log n)。 2. 坐标压缩
3. 计算超越者 countSurpassers 函数计算 数组 中每个元素的超越者数量。
通过这种方法,我们每个元素只检查一次,并且每个元素的结果计算时间为 O(log n)。因此,整个运行时间为 O(n log n)。 4. Main 函数和用户交互
复杂度分析时间复杂度 坐标压缩 对数组中的元素进行排序需要 O(n log n) 时间。可以通过遍历数组并将每个元素的压缩索引放入映射(map)中来在 O(n) 时间内完成。由于排序步骤,坐标压缩的总时间为 O(n log n)。 Fenwick 树操作 对于数组中的每个元素,我们执行两个主要操作:
这两个操作(查询和更新)每个元素都需要 O(log n) 时间,但由于我们对数组中的 n 个元素中的每一个都执行了这两个操作,因此处理所有元素的总时间复杂度为 O(n log n)。 空间复杂度 可以通过考虑算法各个组件使用的内存来分析基于 Fenwick 树的解决方案的空间复杂度。
|
介绍 ODMG (Object Data Management Group) 标准为处理面向对象数据的系统提供了指导。其主要目标是为创建使用对象数据库的应用程序提供框架和接口。通过遵循 ODMG 标准,开发人员可以在供应商平台上构建面向对象的数据库应用程序。一个...
阅读9分钟
参数强制转换也称为隐式类型转换或类型转换。它是 C/C++ 编程语言的一个基本部分。这意味着编译器在必要时会自动从一种数据类型转换为另一种数据类型。这种自动转换可确保兼容性并促进无缝通信……
5 分钟阅读
“连接木棍的最小成本”问题是一个常见的算法任务,其中必须将多个木棍元素合并成一根,成本等于连接的两个木棍长度之和。目标是降低总体成本... ...
11 分钟阅读
此方法主要用于获取 uniform_real_distribution 可以生成的最小可能值。为了在此程序中使用此函数,必须包含 <random> 头文件。<random> 头文件将是生成随机数的一个很好的来源。它的一个组件...
阅读 4 分钟
在本文中,我们将讨论 C++ 中 Odious 数的不同方法和示例。什么是 Odious 数?如果一个数字是正数,并且其二进制展开中的置位位数是奇数,则该数字被认为是 Odious 数。1 是...
阅读 4 分钟
在 C++ 中,Yen 的 K-最短路径算法在加权图中查找源和目的地之间的 K 条最短唯一路径。Yen 的方法通过产生先前确定的路径的偏差来迭代地寻找最短路径(由 Dijkstra 算法发现)。存储了一个优先队列...
阅读 12 分钟
在本文中,我们将讨论 C++ 中的 multimap size() 函数。但在了解 size() 函数之前,我们必须了解 multimap。Multimap 是 C++ 中的一个排序容器,存在于标准模板库中。通常,map 存储键值对...
阅读 3 分钟
简介:Sleep Sort 算法是一种非传统且富有创意的排序数字的方法,它依赖于系统计时来间接实现所需的顺序。Sleep Sort 的基本思想是,较大的数字可以“睡眠”或延迟更长的时间...
阅读 10 分钟
引言:在 C++ 中处理字符串时,正确处理字符编码是必须的。例如,一个常见的任务是将多字节字符串反转为宽字符字符串,反之亦然。这正是 std::wcstombs 功能发挥作用的地方。现在,让我们看看...
阅读 4 分钟
引言:在数论和模运算的领域中,在素数模下寻找平方根的问题很重要,尤其是在密码学和数论应用中。Shanks Tonelli 算法提供了一种有效的方法来计算素数模下的平方根。语法:它包含...
阅读9分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India