- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
免责声明这是我类(class)的练习,而不是来自正在进行的比赛。
问题描述
问题描述很直接:
给定两个数组,A 和 B,分别包含 n 和 m 个元素。您需要排序的数字是 Ai*Bj ,对于 1 <= i <= n 和 1 <= j <= m。简而言之,第一个数组的每个元素都应乘以第二个数组的每个元素。
设 C 是这种排序的结果,是元素的非递减序列。打印此序列每十个元素的和,即 C1 + C11 + C21 + ...。
1 <= n,m <= 6000
1 <= Ai,Bj <= 40000
内存限制:512MB
时间限制:2秒
到目前为止我的解决方案
首先,我使用 Java,使用 Arrays.sort,给定最大的 n,m。我们需要对大小为 36000000 的数组进行排序。然后遍历数组中的每十分之一元素以获得总和。这通过了 23 个测试用例,其余的都获得了 TLE。
然后我切换到C++,同样使用内置的排序方法,结果稍微好一点,通过了29个测试用例。
我的观察
给定这个输入
4 4
7 1 4 9
2 7 8 11
如果我们先对两个数组 A 和 B 进行排序,然后将它们相乘,我们得到
2 8 14 18 7 28 49 63 8 32 56 72 11 44 77 99
这是一个包含 m 个已排序子数组的数组。但是我想不出任何好的解决方案来将所有这些已排序的子数组合并到 O(mn) 或附近的某个地方。或者换个角度看问题,两个数组的每一个元素相乘有什么特殊的性质吗?
更新 1:- 使用 MinHeap - 不够快。 [TLE]
更新 2:- 使用 k 方式合并 - 仍然不够快。 [TLE]
更新 3:- 我忘了提及 A 和 B 中元素的范围,所以我刚刚更新了它。
更新 4:- 基数排序 base 256 [已接受]
结论
通过这个问题,我了解了更多关于排序的一般知识以及一些使用 Java 和 C++ 中的库进行排序的有用信息。
C++ 中内置的排序方法如 std::sort 不稳定,因为它基本上是快速排序,但当数据格式不适合快速排序时,它会切换到归并排序,但通常它是最快的内置的 C++ 类型(除了 qsort、stable_sort)。
对于 Java,有 3 种排序类型,一种是 Arrays.sort(primitive[]),它在底层使用归并排序,Arrays.sort(Object[]),它使用 Timsort 和 Collections.sort它基本上调用 Arrays.sort 来完成繁重的处理工作。
非常感谢@rcgldr 的 radix sort base 256 C++ 代码,它在 6000*6000 个元素的更坏情况下工作得很好,最长运行时间为 1.187s。
最佳答案
merge all of these sorted subarray in O(mn)
产品 < 2^31,所以 32 位整数就足够了,基数排序基数 256 也可以。每 10 个项目的总和可能需要 64 位。
更新 - 你没有在你的评论中提到 256MB 的内存限制,我刚刚注意到这一点。输入数组大小为 6000*6000*4 = 137.33MB。分配原始数组一半大小的工作数组(四舍五入:work_size = (1+original_size)/2 ),最坏情况,3000*6000 个元素(< 210MB 所需总空间)。将原始(产品)数组视为两半,并使用基数排序对原始数组的两半进行排序。将排序后的下半部分移动到工作数组中,然后将工作数组与原始数组的上半部分合并回原始数组。在我的系统(Intel 3770K 3.5 ghz,Win 7 Pro 64 位)上,2 种基数排序将花费不到 0.4 秒(每次约 0.185 秒),一次合并 3000*6000 个整数将花费大约 0.16 秒,不到排序部分为 0.6 秒。使用这种方法,无需在进行乘法运算之前对 A 或 B 进行排序。
是否允许使用 SIMD/xmm 寄存器进行 A 和 B (A o.x B) 的外积乘法?
基于 256 基数排序的示例 C++ 代码:
// a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
return(a);
}
可以使用归并排序,但速度较慢。假设 m >= n,那么传统的 2 路合并排序将采用 O(mn ⌈log2(n)⌉) 对 n 个排序的运行进行排序,每个运行的大小为 m。在我的系统上,对 6000 个整数进行 6000 次排序大约需要 1.7 秒,而且我不知道矩阵乘法需要多长时间。
使用堆或其他形式的优先级队列只会增加开销。传统的 2 路归并排序比使用堆的 k 路归并排序更快。
在一个有 16 个寄存器的系统上,其中 8 个用作工作和结束索引或运行指针,4 路合并排序(没有堆)可能会快一点(大约 15%),它是相同的总数操作次数,1.5 x 比较次数,但 0.5 x 移动次数,这对缓存更友好。
关于java - 将一个数组的每个元素乘以另一个数组的每个元素并对新的非常大的数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55887651/
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 10年前关闭。 Improve this qu
从以下网站,我找到了执行java AD身份验证的代码。 http://java2db.com/jndi-ldap-programming/solution-to-sslhandshakeexcepti
似乎 melt 会使用 id 列和堆叠的测量变量 reshape 您的数据框,然后通过转换让您执行聚合。 ddply,从 plyr 包看起来非常相似..你给它一个数据框,几个用于分组的列变量和一个聚合
我的问题是关于 memcached。 Facebook 使用 memcached 作为其结构化数据的缓存,以减少用户的延迟。他们在 Linux 上使用 UDP 优化了 memcached 的性能。 h
在 Camel route ,我正在使用 exec 组件通过 grep 进行 curl ,但使用 ${HOSTNAME} 的 grep 无法正常工作,下面是我的 Camel 路线。请在这方面寻求帮助。
我正在尝试执行相当复杂的查询,在其中我可以排除与特定条件集匹配的项目。这是一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我正在尝试执行相当复杂的查询,我可以在其中排除符合特定条件集的项目。这里有一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我发现了很多嵌入/内容项目的旧方法,并且我遵循了在这里找到的最新方法(我假设):https://blog.angular-university.io/angular-ng-content/ 我正在尝试
我正在寻找如何使用 fastify-nextjs 启动 fastify-cli 的建议 我曾尝试将代码简单地添加到建议的位置,但它不起作用。 'use strict' const path = req
我正在尝试将振幅 js 与 React 和 Gatsby 集成。做 gatsby developer 时一切看起来都不错,因为它发生在浏览器中,但是当我尝试 gatsby build 时,我收到以下错
我试图避免过度执行空值检查,但同时我想在需要使代码健壮的时候进行空值检查。但有时我觉得它开始变得如此防御,因为我没有实现 API。然后我避免了一些空检查,但是当我开始单元测试时,它开始总是等待运行时异
尝试进行包含一些 NOT 的 Kibana 搜索,但获得包含 NOT 的结果,因此猜测我的语法不正确: "chocolate" AND "milk" AND NOT "cow" AND NOT "tr
我正在使用开源代码共享包在 iOS 中进行 facebook 集成,但收到错误“FT_Load_Glyph failed: glyph 65535: error 6”。我在另一台 mac 机器上尝试了
我正在尝试估计一个标准的 tobit 模型,该模型被审查为零。 变量是 因变量 : 幸福 自变量 : 城市(芝加哥,纽约), 性别(男,女), 就业(0=失业,1=就业), 工作类型(失业,蓝色,白色
我有一个像这样的项目布局 样本/ 一种/ 源/ 主要的/ java / java 资源/ .jpg 乙/ 源/ 主要的/ java / B.java 资源/ B.jpg 构建.gradle 设置.gr
如何循环遍历数组中的多个属性以及如何使用map函数将数组中的多个属性显示到网页 import React, { Component } from 'react'; import './App.css'
我有一个 JavaScript 函数,它进行 AJAX 调用以返回一些数据,该调用是在选择列表更改事件上触发的。 我尝试了多种方法来在等待时显示加载程序,因为它当前暂停了选择列表,从客户的 Angul
可能以前问过,但找不到。 我正在用以下形式写很多语句: if (bar.getFoo() != null) { this.foo = bar.getFoo(); } 我想到了三元运算符,但我认
我有一个表单,在将其发送到 PHP 之前我正在执行一些验证 JavaScript,验证后的 JavaScript 函数会发布用户在 中输入的文本。页面底部的标签;然而,此消息显示短暂,然后消失...
我是一名优秀的程序员,十分优秀!