两个有序数组,将其合并成一个有序数组
思路1,先合并,然后排序;不优雅!
merge (arr1, arr2) {
return arr1.concat(arr2).sort((a, b) => a - b);
}
双指针的写法
思路是新建一个长度为和的新数组,指针m指向数组1的最后,n指向数组2的最后,p表示新数组的最后,如果m > n,则m比数组2的所有都大,把m的值付给新数组的p的位置,并p-1;反之则n比数组1的值都大,放到p的位置
merge (arr1, arr2) {
let len1 = arr1.length,
len2 = arr2.length,
m = len1 - 1,
n = len2 - 1;
if (m < 0 || n < 0) { // 如果有一个数组为空,展开后直接返回
return [...arr1, ...arr2];
}
if (arr1[0] > arr2[n]) { // 如果arr1的第一个比arr2的最后一个还大,concat后返回
return arr2.concat(arr1);
}
if (arr2[0] > arr1[m]) { // 同上 处理特殊情况 非必须
return arr1.concat(arr2);
}
let arr = arr1.concat(new Array(len2).fill(0)), // 新建一个数组,将arr1放进去后补0到两数组和的长度
p = arr.length - 1; // p代表返回数组的最后一个
while (n >= 0) { // n代表目标数组的指针
if (arr[m] > arr2[n]) { // 如果n小于arr的m,把m放到p的位置
arr[p] = arr[m];
m--;
} else { // n大于或等于m 把n放到最后面
arr[p] = arr2[n];
n--;
}
p--;
}
return arr;
}
可优化的地方是,while跳出循环的条件为两个数组其一的指针走到了头(小于0),若n < 0,则数组2中的数值都在arr中找到了位置,如果m < 0,那么说明数组2中剩余的所有值都比arr中的值小,则把arr剪切n + 1的长度,并把arr2中的剩余值拼接上
function merge (arr, arr2, arr1) {
let len1 = arr1.length,
len2 = arr2.length,
m = len1 - 1,
n = len2 - 1;
let arr = arr1.concat(new Array(len2).fill(0)), // 新建一个数组,将arr1放进去后补0到两数组和的长度
p = arr.length - 1; // p代表返回数组的最后一个
while(m >= 0 && n >= 0) {
// 注意--符号在后面,表示先进行计算再减1,这种缩写缩短了代码
arr[p--] = arr[m] > arr2[n] ? arr[m--] : arr2[n--];
}
arr.splice(0, n + 1, ...arr2.slice(0, n + 1)); // 处理m < 0时 循环跳出,说明arr2剩余元素都比arr中的小了,所以直接剪裁拼接就ok了
return arr;
}