我正在尝试定义一个合并功能,当给定两个包含数字的排序数组时,该函数将从两个列表中返回数字的排序数组。
merge([ 4, 5, 6 ], [ 1, 2, 3, 4 ]) => [ 1, 2, 3, 4, 4, 5, 6 ]
merge([ 4 ], [ 2, 5, 8 ]) => [ 2, 4, 5, 8 ]
merge([ 1, 2, 6 ], []) => [ 1, 2, 6 ]
这是我的代码:
function merge(arr1, arr2) {
return arr1.concat(arr2).sort(arr1, arr2);
}
虽然输出正确,但从我的研究及其自动化测试中得知,此代码的格式不正确。它写道:
不处理两个相同长度的数组。
不处理较短的第一个数组。
不处理较短的第二个数组。
编写此代码的更好方法是什么?我该怎么做更好?
答案 0 :(得分:3)
您的代码看起来不错,但是您使用\\/@\\b\\r\\t\\Z\\%\\n\\0\\_\\'\\\"
的方式不正确。
一种使用sort的方法是提供一个比较数组中两个值的函数,并返回一个数字(正数或负数)来指示这些值的排序。有关排序的更多信息,请see this article
请考虑对合并方法进行以下更改:
var result = new RegExp('(?<=\"compliantNotes\": \").*(?=\"\s+\"compliantDetected\":)', 'sgmi').exec(inputString);
答案 1 :(得分:3)
其他答案已经为您提供了如何使代码正确的字面答案。但是,它可能没有抓住重点。您描述的函数用于构建“合并排序”,这是一个非常重要的排序算法,其主要优点是只需要按顺序读取一次输入列表即可,从而导致每遍O(N)的复杂性;这样,它甚至可以对内存中无法容纳的内容进行排序。您的代码不执行此操作-它依赖于sort
,每次调用函数时它都为O(N log(N)),并且它没有利用其两个输入均已预先排序的事实(这是合并排序的关键要求)。
合并排序算法将从两个列表中获取第一个元素,然后追加较小的元素。然后,它将该列表中的下一个元素与另一个列表的第一个元素进行比较,并再次取较小的一个。重复进行,直到用尽一个列表,然后追加其余的列表。 (您可以在Wikipedia page上找到有关合并排序的更详尽的说明)。
答案 2 :(得分:3)
Amadan的answer注意问题约束,并指出可以用O(n)时间编写。本质上,当对输入都进行排序时,算法是合并排序中的“合并”步骤。这是以线性时间完成的,并且以非常简单和令人愉悦的方式工作:查看每个列表的第一项,并从两个列表中取较小的一个,直到用尽一个或两个列表。然后,将所有剩余元素添加到结果数组上并返回。
其他答案很好,并且具有良好的JS风格,但是使用的时间为O(n log n),并且完全忽略了对数组进行预排序而没有提及的问题,这几乎肯定不是有人要求此例程的答案在寻找。
这是合并步骤:
const merge = (a, b) => {
const result = [];
while (a.length && b.length) {
result.push(a[0] < b[0] ? a.shift() : b.shift());
}
return result.concat(a).concat(b);
};
console.log(merge([ 4, 5, 6 ], [ 1, 2, 3, 4 ])); // => [ 1, 2, 3, 4, 4, 5, 6 ]
console.log(merge([ 4 ], [ 2, 5, 8 ])); // => [ 2, 4, 5, 8 ]
console.log(merge([ 1, 2, 6 ], [])); // => [ 1, 2, 6 ]
这也可以通过保留原始数组的索引来完成,该索引速度更快,但是看起来有点难看。
这是JSPerf的基准。
答案 3 :(得分:1)
仅concat
个数组,并在应用简单的sort
函数之后返回:
console.log(merge([4, 5, 6], [1, 2, 3, 4])); //[ 1, 2, 3, 4, 4, 5, 6 ]
console.log(merge([4], [2, 5, 8])); //[ 2, 4, 5, 8 ]
console.log(merge([1, 2, 6], [])); //[ 1, 2, 6]
function merge(a, b) {
return a.concat(b).sort((a, b) => a - b);
}