前端练习42 数组中数据归并

博客介绍了如何在原地对数组进行归并排序,以解决数组从两端升序排列的问题。通过归并排序的思路,避免创建新数组,直接修改原有数组达到排序目的。内容包括题目描述、实现方法以及复习归并排序算法。
摘要由CSDN通过智能技术生成

知识点

归并排序算法

题目

有一个数组,这个数组从两个地方开始升序,一个是开始,一个是中间。例如:

[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;
};

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值