知识点
归并排序算法
题目
有一个数组,这个数组从两个地方开始升序,一个是开始,一个是中间。例如:
[10, 21, 32, 11, 16, 40] // 从 0 和 3 开始升序
[1, 5, 10, 11, 3, 4, 8, 12, 30] // 0 和 4 开始升序
请你完成merge
函数,可以把类似上面的数组变成一个完全升序的数组(直接修改原来的数组)。你不能用sort
方法,并且只能使用一次循环。
实现
这道题的思路可以使用归并排序,只是不能返回新的数组,需要在原有的数组上进行修改
可以复制出两个数组,然后将原数组通过splice
方法清空,将归并比较的结果插入到原来的数组:
const merge = arr => {
const middleIndex = Math.floor(arr.length / 2);
let left = arr.slice(0, middleIndex);
let right = arr.slice(middleIndex);
// 清空原数组
arr.splice(0, arr.length);
// 递归排序
while (left.length && right.length) {
arr.push((left[0] < right[0] ? left : right).shift());
if (left.length === 0) {
arr.push(...right)
} else if (right.length === 0) {
arr.push(...left)
}
}
return arr;
}
也可以直接对原来的数组进行修改:
const merge = (arr) => {
const middle = Math.floor(arr.length / 2);
let prev = arr.slice(0, middle);
let next = arr.slice(middle);
while (prev.length && next.length) {
const temp = (prev[0] < next[0] ? prev : next);
const index = arr.indexOf(temp[0]);
arr.push(arr.splice(index, 1)[0]);
temp.shift();
}
const rest = prev.length === 0 ? next : prev;
arr.splice(0, rest.length);
arr.push(...rest);
return arr;
};
注意上面对arr
最后一次性处理的时候,不能直接将arr.splice(0, rest.length)
直接插入到arr
最后,因为arr.splice(0, rest.length)
有可能有左右两个部分的数据,所以要使用prev
或者next
中不为空的那个
复习
顺道复习一下数组的归并排序算法:
const sort = (arr, s = 0, e = arr.length - 1) => {
if (s > e) {
return []
} else if (s === e) {
return [arr[s]]
}
const middleIndex = Math.floor((s + e) / 2);
let left = sort(arr, s, middleIndex);
let right = sort(arr, middleIndex + 1, e);
let result = [];
while (left.length && right.length) {
const temp = (left[0] < right[0] ? left : right).shift();
result.push(temp);
if (left.length === 0) {
result.push(...right)
} else if (right.length === 0) {
result.push(...left)
}
}
return result;
};