今天在抖音上看到一个这样的题目,好像很多地方都见过,比较基础,提供一些可能高效的解决思路,在算法选择最优解的基础上,继续优化代码细节,让效率快2-3倍,并进行扩展应用。
现有两个有序数组,例如
jsconst a = [1, 3, 5];
const b = [2, 4, 6];
需要实现一个函数,将这两个有序数组按元素大小进行合并吗,得到以下结果
js[1, 2, 3, 4, 5, 6];
看着好像蛮简单的,思路可能也很多。在工作里面,如果不考虑效率,可能就这样做了。
jsfunction mergeArr (a, b) {
return [...a, ...b].sort((a, b) => a - b);
}
这样,不能说没得到解决,但是在面试里如果这样写,基本是等于没写。
我建议是用双指针的形式来写。
双指针遍历(时间复杂度 O(m+n))
然后因为这两个数组可能长度不是对等的,会导致有数组存在剩余元素的情况。
剩余元素处理(时间复杂度 O(k))
js
function mergeSortedArrays(a, b) {
const merged = [];
let i = 0, j = 0;
while (i < a.length && j < b.length) {
a[i] <= b[j] ? merged.push(a[i++]) : merged.push(b[j++]);
}
return merged.concat(a.slice(i)).concat(b.slice(j));
}
在这个场景下,这种写法应该是性能最优的。
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
双指针 | O(m+n) | O(m+n) | 已排序数组合并 |
快速排序 | O((m+n)log(m+n)) | O(m+n) | 未排序数组合并 |
插入排序 | O(mn) | O(1) | 小规模数组合并 |
在之前算法的基础上,可以在很多更细节的角度来优化性能,毕竟在面试中,100分的人就是比99分的人更有机会。
jsfunction mergeSortedArraysPlus(a, b) {
const totalLength = a.length + b.length;
const merged = new Array(totalLength);
let i = 0, j = 0, k = 0;
while (i < a.length && j < b.length) {
merged[k++] = a[i] <= b[j] ? a[i++] : b[j++];
}
while (i < a.length) merged[k++] = a[i++];
while (j < b.length) merged[k++] = b[j++];
return merged;
}
优化点:
通过实际的数据测试中,进阶优化的版本会比原版本快2-3倍。
几个小细节的优化就在算法思路不变的前提下,性能又强了2-3倍...fucking crazy
在面试中,往往面试官都喜欢在一个角度追着问。既然题目是合并两个有序数组,那如果是合并多个有序数组呢。
思维开阔一点,就能很快get到原理其实没变,可以借助现有JS
方法一行代码实现。
jsfunction mergeKSortedArrays(arrays) {
return arrays.reduce(mergeSortedArraysPlus, []);
}
mergeSortedArraysPlus
就是上面进阶优化版本的实现函数。
本文作者:CreatorRay
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!