Codility 的复杂性达到顶峰

2024-04-25

我刚刚完成了以下 CodilityPeaks http://codility.com/demo/take-sample-test/peaks问题。问题如下:


给出一个由 N 个整数组成的非空零索引数组 A。 峰值是大于其邻居的数组元素。更准确地说,它是一个索引 P,满足 0 A[P + 1]。 例如下面的数组A:

A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2

正好有三个峰值:3、5、10。 我们想要将该数组分成包含相同数量元素的块。更准确地说,我们想要选择一个数字 K,它将产生以下块: A[0], A[1], ..., A[K − 1], A[K], A[K + 1], ..., A[2K − 1], ... A[N − K], A[N − K + 1], ..., A[N − 1]。 更重要的是,每个块应该至少包含一个峰值。请注意,块的极端元素(例如 A[K − 1] 或 A[K])也可以是峰值,但前提是它们具有两个邻居(包括相邻块中的一个)。 目标是找到数组 A 可以分为的最大块数。 数组A可以分为如下的块:

一块 (1, 2, 3, 4, 3, 4, 1, 2, 3, 4, 6, 2)。该块包含三个峰。

两个块 (1, 2, 3, 4, 3, 4) 和 (1, 2, 3, 4, 6, 2)。每个区块都有一个峰值。

三个块 (1, 2, 3, 4), (3, 4, 1, 2), (3, 4, 6, 2)。每个区块都有一个峰值。

请特别注意,第一个块 (1, 2, 3, 4) 在 A[3] 处有一个峰值,因为 A[2] A[4],即使 A[4] 在相邻块。 但是,数组 A 不能分为四个块:(1, 2, 3)、(4, 3, 4)、(1, 2, 3) 和 (4, 6, 2),因为 (1, 2, 3) 块不包含峰。特别注意 (4, 3, 4) 块包含两个峰值:A[3] 和 A[5]。 数组A最多可以分为3个块。

写一个函数: 类解决方案 { 公共 int 解决方案(int[] A); } 给定一个由 N 个整数组成的非空零索引数组 A,返回 A 可以分为的最大块数。 如果 A 无法分为一定数量的块,则该函数应返回 0。 例如,给定:

A[0] = 1
A[1] = 2 
A[2] = 3 
A[3] = 4 
A[4] = 3 
A[5] = 4 
A[6] = 1 
A[7] = 2 
A[8] = 3 
A[9] = 4 
A[10] = 6 
A[11] = 2

该函数应返回 3,如上所述。 假使,假设:

N是[1..100,000]范围内的整数; 数组 A 的每个元素都是 [0..1,000,000,000] 范围内的整数。

复杂:

预期最坏情况时间复杂度为 O(N*log(log(N)))

预期最坏情况的空间复杂度为 O(N),超出输入存储(不计算输入参数所需的存储)。

可以修改输入数组的元素。


我的问题

因此,我用对我来说似乎是蛮力解决方案来解决这个问题 - 遍历每个组的大小1..N,并检查每组是否至少有一个峰值。在我试图解决这个问题的前 15 分钟,我试图找出一些更优化的方法,因为所需的复杂性是 O(N*log(log(N)))。

这是我的“暴力”代码,它通过了所有测试,包括大型测试,得分为 100/100:

public int solution(int[] A) {
    int N = A.length;

    ArrayList<Integer> peaks = new ArrayList<Integer>();
    for(int i = 1; i < N-1; i++){
        if(A[i] > A[i-1] && A[i] > A[i+1]) peaks.add(i);
    }

    for(int size = 1; size <= N; size++){
        if(N % size != 0) continue;
        int find = 0;
        int groups = N/size;
        boolean ok = true;
        for(int peakIdx : peaks){
            if(peakIdx/size > find){
                ok = false;
                break;
            }
            if(peakIdx/size == find) find++;
        }
        if(find != groups) ok = false;
        if(ok) return groups;
    }

    return 0;
}

我的问题是如何推断出这实际上是 O(N*log(log(N))),因为它对我来说一点也不明显,而且我很惊讶我通过了测试用例。我正在寻找即使是最简单的复杂性证明草图,也能让我相信这个运行时。我假设 log(log(N)) 因子意味着在每次迭代中通过平方根减少问题,但我不知道这如何应用于我的问题。非常感谢您的帮助


您是完全正确的:要获得日志日志性能,需要减少问题。

python 中的 n.log(log(n)) 解决方案[如下]。 Codility 不再测试此问题的“性能”(!),但 Python 解决方案的准确性得分为 100%。

正如您已经猜测的那样:外循环将是 O(n)因为它正在测试每个大小的块是否是干净的除数内循环必须是 O(log(log(n)))总体上给出 O(n log(log(n))) 。

我们可以获得良好的内循环性能,因为我们只需要执行 d(n),即 n 的除数数。我们可以存储前缀和迄今为止的峰值,它使用问题规范允许的 O(n) 空间。检查每个“组”中是否出现峰值是使用组开始和结束索引的 O(1) 查找操作。

按照这个逻辑,当候选块大小为 3 时,循环需要执行 n/3 峰值检查。复杂度变为总和:n/a + n/b + ... + n/n,其中分母 (a, b, ...) 是 n 的因子。

短篇故事:n.d(n) 操作的复杂度为 O(n.log(log(n)))。

更长的版本:如果您参加过 Codility 课程,您会记得第 8 课:素数和合数 https://codility.com/media/train/8-PrimeNumbers.pdf谐波数运算之和将给出 O(log(n)) 复杂度。我们有一个缩减集,因为我们只考虑因子分母。第 9 课:埃拉托斯特尼筛法 https://codility.com/media/train/9-Sieve.pdf展示了素数倒数之和如何为 O(log(log(n))) 并声称“证明是不平凡的”。在这种情况下维基百科 http://en.wikipedia.org/wiki/Divisor_function告诉我们除数之和 sigma(n) 有一个上限(参见罗宾不等式,大约在页面的中间)。

这完全回答了你的问题吗?也非常欢迎有关如何改进我的 python 代码的建议!

def solution(data):

    length = len(data)

    # array ends can't be peaks, len < 3 must return 0    
    if len < 3:
        return 0

    peaks = [0] * length

    # compute a list of 'peaks to the left' in O(n) time
    for index in range(2, length):
        peaks[index] = peaks[index - 1]

        # check if there was a peak to the left, add it to the count
        if data[index - 1] > data[index - 2] and data[index - 1] > data[index]:
            peaks[index] += 1

    # candidate is the block size we're going to test
    for candidate in range(3, length + 1):

        # skip if not a factor
        if length % candidate != 0:
            continue

        # test at each point n / block
        valid = True
        index = candidate
        while index != length:

            # if no peak in this block, break
            if peaks[index] == peaks[index - candidate]:
                valid = False
                break

            index += candidate

        # one additional check since peaks[length] is outside of array    
        if index == length and peaks[index - 1] == peaks[index - candidate]:
            valid = False

        if valid:
            return length / candidate

    return 0

Credits:感谢 @tmyklebu 的贡献所以答案 https://stackoverflow.com/questions/26150180/onloglogn-algorithm-for-codilitys-peaks这对我有很大帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Codility 的复杂性达到顶峰 的相关文章

  • 直观地执行不同的排序算法[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Python 中的空填字游戏求解器

    我得到了一个包含填字游戏蓝图的矩阵 当然 它是空的 我们的目标是填补整个难题 这是 Checkio 的一项任务 我已经为此奋斗了相当长一段时间 根据我对复杂性的理解 这个问题没有完美的算法 不过 必须有最好的方法来做到这一点 对吧 我尝试了
  • 计算具有 3 个循环的算法的复杂度

    我尝试解决以下练习 以下代码片段最坏情况运行时间的增长顺序是什么 作为 N 的函数 int sum 0 for int i 1 i lt N i for int j 1 j lt i i j for int k 1 k lt j j k s
  • 运行时间为 O(n) 且就地排序的排序算法

    有没有运行时间为O n 并且还分类到位 在某些情况下 最好的情况是 O n 但这可能是因为项目集合已经排序 你正在看 O nlogn 一些较好的平均值 话虽如此 排序算法的 Wiki 还是相当不错的 有一个表格比较了流行的算法 说明了它们的
  • 填充体积算法

    我有一个具有一定尺寸长度 宽度 高度的盒子 我有不同长度 宽度 高度的物品 是否有现有的算法可以确定放入盒子中的最佳物品 这称为装箱 切割库存 背包问题 并且是 NP 难问题 一般来说 您只能通过使用启发式方法获得近似解 请参见示例 htt
  • 在 3d 网格中转发(绘制)线

    我需要类似 Bresenham 算法的东西 但是 对于 3d 网格空间来说不完全是这样 我需要 3d 单元网格 边缘尺寸 1 0 从 S 点开始 前进到 K 点 接触 该线接触的所有单元格 即使只有边缘 点被触摸我需要触摸所有 8 个单元
  • 序列和与 GCD

    大约一个月前 我在编程挑战中遇到了这个问题 但社论尚未发布 所以我在这里问 有一个大小为 N 的数组 A 求 A 的 K 个长度子序列的总和 GCD Example 如果 A 1 2 3 且 K 2 1 2 3 总和 1 GCD 3 1 3
  • 如何在 JavaScript 中构建树模式匹配算法?

    好吧 这是一个有点复杂的问题 但是 tl dr 基本上是如何使用 模式树 解析 实际树 如何检查特定的树实例是否与特定的模式树匹配 首先 我们有我们的结构模式树 模式树通常可以包含以下类型的节点 sequence节点 匹配一系列项目 零个或
  • Python Pandas:沿一列比较两个数据帧,并返回另一个数据帧中两个数据帧的行内容

    我正在处理两个 csv 文件并作为数据框 df1 和 df2 导入 df1 有 50000 行 df2 有 150000 行 我想将 df2 的 时间 与 df1 求时间差并返回所有列的值 对应相似的行 保存在df3中 时间同步 例如 35
  • 分而治之算法找到两个有序元素之间的最大差异

    给定一个整数数组 arr 找出任意两个元素之间的差异 使得较大的元素出现在 arr 中较小的数字之后 Max Difference Max arr x arr y x gt y 例子 如果数组是 2 3 10 6 4 8 1 7 那么返回值
  • Java 2d 游戏中的路径查找?

    本质上它是我正在开发的一款吃豆人克隆游戏 我有一个 Enemy 类 并创建了该类的 4 个实例 它们都代表游戏的 4 个幽灵 所有幽灵都会在屏幕的随机区域启动 然后它们必须朝着吃豆人角色前进 当玩家控制吃豆人并移动它时 他们应该跟随它并尽可
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 使用什么算法来确定使系统达到“零”状态所需的最小操作数?

    这是一种更通用的问题 不是特定于语言的 有关要使用的想法和算法的更多信息 系统如下 它登记朋友群体之间的小额贷款 Alice and Bill要去吃午饭 比尔的卡坏了 所以爱丽丝支付了他的餐费 10 美元 第二天Bill and Charl
  • 测试 python Counter 是否包含在另一个 Counter 中

    如何测试是否是pythonCounter https docs python org 2 library collections html collections Counter is 包含在另一个中使用以下定义 柜台a包含在计数器中b当且
  • 覆盖二维平面上给定点的最小圆

    问题 覆盖 2D 平面上给定 N 个点的圆的最小可能直径是多少 解决这个问题最有效的算法是什么 它是如何工作的 这是最小圆问题 http en wikipedia org wiki Smallest circle problem 请参阅参考
  • 用于查找最近邻居的空间划分算法如何工作?

    为了找到最近的邻居 空间分区 http en wikipedia org wiki Nearest neighbor search Space partitioning是算法之一 它是如何工作的 假设我有一组 2D 点 x 和 y 坐标 并
  • 当满足动态条件时退出递归函数

    使用来自的函数生成汉明距离 t 内的所有比特序列 https stackoverflow com questions 40813022 generate all sequences of bits within hamming distan
  • sigmoid 的导数

    我正在使用反向传播技术创建一个神经网络进行学习 我知道我们需要找到所使用的激活函数的导数 我正在使用标准 sigmoid 函数 f x 1 1 e x 我已经看到它的导数是 dy dx f x f x 1 f x 这可能是一个愚蠢的问题 但
  • Z 算法背后的直觉

    Z算法是一种复杂度为O n 的字符串匹配算法 一种用例是从字符串 B 中查找字符串 A 的最长出现次数 例如 overdose from stackoverflow 将会 over 您可以通过使用组合字符串调用 Z 算法来发现这一点 ove

随机推荐

  • 不获取AudioListenerInterruptionEnd触发器

    我对 OpenAl 和 MPMoviePlayerController 的组合有疑问 我在 OpenAl 设置过程中注册了 AudioInterruptionLister 当我开始播放视频时 侦听器会收到 AudioListenerInte
  • 离子 3 角度 4 动画不起作用

    我有一个组件 我正在尝试为手风琴列表设置动画 我已经进行了所有更改 例如包括import BrowserModule from angular platform browser and import BrowserAnimationsMod
  • std::unordered_set 迭代器遍历的复杂性

    我最近玩了一个std unordered set http en cppreference com w cpp container unordered set 我怀疑我的 STL 版本会跟踪某些 FILO 数据结构 看起来像列表 中的非空存
  • Android JSON解析并存储到数据库

    我正在制作一个具有数据库的应用程序 现在我正在尝试从中解析数据值
  • Kafka Streams - 减少大型状态存储的内存占用

    我有一个拓扑 见下文 可以读取一个非常大的主题 每天超过十亿条消息 这个 Kafka Streams 应用程序的内存使用量相当高 我正在寻找一些关于如何减少状态存储占用空间的建议 更多详细信息如下 Note 我并不是想逃避国有商店 我只是认
  • 清除给定 iOS 应用程序的 cookie

    我的应用程序连接到服务器 并且基于 cookie 服务器将发出不同的响应 是否无法以编程方式清除cookie存储 以便服务器下次联系服务器时无法识别我的应用程序 据我所知 清除 Settings app 中的 Cookie 仅适用于 Saf
  • 如何用R中的频率表获得中位数? [复制]

    这个问题在这里已经有答案了 Problem 我改变了问题的表述 因为似乎缺乏清晰度 所以 我们有数千家医院 他们的患者年龄在 0 岁到 100 岁之间 对于每个年龄段 他们都有一定数量的患者 例如Hospital1 有 10 名 1 岁患者
  • 动态获取路由路径

    我最近将一些模板从 ERB 转换为 Haml 大多数情况下 它变得更干净 更好 但按钮定义开始变得糟糕 我想转换这个 link to t new default gt t helpers links new new intern path
  • Python ctypes 指向结构体指针的指针

    我在获取指向工作结构的指针时遇到问题 这是我抛出异常 ArgumentError 参数 1 预期 LP LP List 实例而不是指向 LP LP List 的指针 的代码 class List Structure fields head
  • 如何将额外参数传递给 R 中 do.call 的函数参数

    我想传递参数 stringsAsFactors FALSE to rbind in do call 但以下方法不起作用 data lt do call rbind strsplit readLines home jianfezhang ad
  • 用python计算逻辑回归

    我尝试计算逻辑回归 我有 csv 文件形式的数据 看起来像 node id second major gender major index year dorm high school student fac 0 0 2 257 2007 1
  • 为什么 ts-toolbelt 库使用“Oextendsunknown”表达式

    我正在研究 ts toolbelt 库的源代码 而我也经常遇到这样的表情O extends unknown 在我看来 它没有添加任何功能 所以我想知道 它是做什么用的 hidden export type UnionOf
  • Cypher - 匹配两个不同的可能路径并返回两者

    我有一个数据集 我在这里作为示例表示 http console neo4j org id 3dq78v http console neo4j org id 3dq78v 我想要做的是对于图表中的每个 Z 节点 该示例只有一个 但我有很多 我
  • 苹果组合框架:如何并行执行多个发布者并等待所有发布者完成?

    我正在发现组合 我编写了以 组合 方式发出 HTTP 请求的方法 例如 func testRawDataTaskPublisher for url URL gt AnyPublisher
  • 使用不同的配置文件设置 Git 的开发和测试分支

    我们有一个 WordPress 安装 它有不同的实时 测试 开发配置文件 我知道如何让 Git 忽略wp config php文件 但我想在每个分支中有一个不同的 WP config 文件 这样当开发人员切换到 Dev 时 它将使用 Dev
  • 龙卷风 websocket 应用程序中的用户身份验证

    现在 我提高了我的龙卷风技能 并有一个关于用户身份验证的问题 我的解决方案是在首页上创建安全令牌 然后将其与其他数据一起发送 从 javascript 到龙卷风服务器 在其中检查和验证用户 我想到了 cookie 但我不知道如何读取 coo
  • Sql Server 数据库项目 - VS 2013 中缺少模板

    在 VS2012 中 我使用 Sql Server 数据库项目来管理我的数据库 我尝试将 Db 项目添加到新的 VS2013 解决方案中 但我似乎找不到模板 我在网上和已安装的模板中查看过 有任何想法吗 对我来说 它列在 其他语言 下 我有
  • 将等号('=')传递给 MediaWiki 模板中的参数

    如何在模板参数中使用 字符而不破坏模板解析器 我不是 MediaWIKI 开发人员 所以我没有调试代码或检查日志 我希望这里有人提供转义传递给模板的字符的提示 使用以下内容创建一个名为 Test 的模板 1 像这样 Test R 3 2 1
  • 使用curl解压gzip数据

    I added curl easy setopt client CURLOPT ENCODING gzip 到我的代码 我预计curl 会导致服务器发送压缩数据并解压缩它 实际上我在 HTTP 标头中看到数据被压缩 变化 Accept En
  • Codility 的复杂性达到顶峰

    我刚刚完成了以下 CodilityPeaks http codility com demo take sample test peaks问题 问题如下 给出一个由 N 个整数组成的非空零索引数组 A 峰值是大于其邻居的数组元素 更准确地说