我应该如何优化我的代码?
给定两个排序数组 arr1[]
大小 N
以及 arr2[]
大小 M
. 每个数组按非降序排序。将两个数组按非降序合并为一个排序数组,而不使用任何额外的空间。
例1:
输入:
N = 4, M = 5
arr1[] = {1, 3, 5, 7}
arr2[] = {0, 2, 6, 8, 9}
输出:
0 1 2 3 5 6 7 8 9
说明:由于不能使用任何额外的空间,请修改给定的数组以形成:
arr1[] = {0, 1, 2, 3}
arr2[] = {5, 6, 7, 8, 9}
class Solution {
public void merge(int arr1[], int arr2[], int n, int m) {
for (int k = 0; k < n; k++) {
boolean c = false;
if (arr1[k] > arr2[0]) {
int temp = arr1[k];
arr1[k] = arr2[0];
arr2[0] = temp;
c = true;
}
if (c) {
int minIndex = 0;
for (int i = 0; i < m; i++) {
if (arr2[i] < arr2[minIndex])
minIndex = i;
}
int t = arr2[minIndex];
arr2[minIndex] = arr2[0];
arr2[0] = t;
}
}
for (int i = 0; i < m - 1; i++) {
int minIndex = i;
for (int j = i; j < m; j++) {
if (arr2[j] < arr2[minIndex]) {
minIndex = j;
}
}
int temp = arr2[i];
arr2[i] = arr2[minIndex];
arr2[minIndex] = temp;
}
}
}
2条答案
按热度按时间8oomwypt1#
这是一个稍微简单一点的版本。它仍然具有相同的二次时间复杂度o(n*m),但执行速度比发布的代码快10倍,因此它确实符合优化版本的要求:
不使用额外空间的合并是一个非常严格的约束:您是否认为局部变量是额外空间?如果允许有限的额外空间(例如128个元素的单个数组),则可以找到更快的解决方案,对于中等大小的数组(超过5000个元素),其执行速度比发布的代码快500到2000倍,但对于大型数组,其时间复杂度仍然是二次的。
这是一个高级解决方案(对于500k元素的阵列,速度提高了1000倍):
临时存储将以c或c++等语言在堆栈(自动存储)上分配,以获得最佳效率。
这是一个更有效的方法,在病理样本上的性能更好,在随机内容上的速度快2.5倍:
减小临时存储大小几乎线性地减慢执行时间:
merge_chrlie2
仍然比使用12个元素的本地数组发布的代码快100倍,这很难被视为额外存储。我在c中运行了一个基准测试,使用无空间合并函数作为经典的自顶向下递归合并排序的合并阶段。以下是包含128个元素的临时数组的计时(*):
以下是仅包含5个元素的临时数组的计时:
(*)计时(毫秒),外推
chqrlie
以及shivam
分别适用于大于50k和200k的阵列。mzaanser2#
因为不能使用任何额外的空间,所以可以同时对这两个数组实现一种选择排序
n + m
,检查每个索引是否已在第二个数组中:另请参见:java选择排序