【算法】归并排序 LeetCode148.排序链表

一、归并排序原理

在这里插入图片描述

1.归并排序是一种分而治之的算法。其思想是将原始数组切割分成较小的数组,直到每个数组中只有一个元素,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
2.算法分为两个函数一个是划分mergeSort,采用递归的方式将大数组分割成小数组。
划分是一个递归过程,它需要一个终止条件,就是判断数组的长度是否为一,如果是,则返回这个数组。
如果数组的长度不为一,将其继续划分为小数组,首先得找到数组的中间位mid,找到后将数组分为两个小数组left和right,left数组由索引0到mid的元素组成,right数组由索引为mid到最后一位的元素组成,继续对left和right数组调用划分函数。
3.第二个函数是归并函数merge,该函数接收两个数组作为参数,并将它们归并成一个大数组,排序发生在归并过程中。归并函数的本质就是对传进来的两个数组进行排序,并返回排序后的新数组。
4.时间复杂度O(nlog(n))

二、代码实现

const merger = (leftArr, rightArr) => {
    let left_len = leftArr.length
    let right_len = rightArr.length
    let arr = []
    let i = 0
    let j = 0
    while (i < left_len && j < right_len) {
         leftArr[i] < rightArr[j] ? arr.push(leftArr[i++]) : arr.push(rightArr[j++])
    }
    while (i < left_len) {
         arr.push(leftArr[i++])
    }
    while (j < right_len) {
         arr.push(rightArr[j++])
    }
    return arr
 }
 const mergeSort = (arr) => {
      let length = arr.length
      if (length <= 1) {
           return arr
      }
      let mid = Math.floor(length / 2)
      let leftArr = arr.slice(0, mid)
      let rightArr = arr.slice(mid)
      return merger(mergeSort(leftArr), mergeSort(rightArr)); //合并左右部分
}

三、例题LeetCode148

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例 1:

输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:

输入:head = []
输出:[]

提示:

链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105

题解

该题是对链表进行归并排序,因此要在数组的基础上上升到链表,但原理是相同的。两个小链表归并可以参考LeetCode21.合并两个有序链表
以下是代码实现

var merge = function (left, right) {
      var dummy = new ListNode(0, null);
      var temp = dummy, temp1 = left, temp2 = right;
      while (temp1 !== null && temp2 !== null) {
           if (temp1.val < temp2.val) {
                temp.next = temp1;
                temp1 = temp1.next;
           } else {
                temp.next = temp2;
                temp2 = temp2.next;
           }
           temp = temp.next;
       }
       if (temp1 !== null) {
            temp.next = temp1;
       } else {
            temp.next = temp2
       }
       return dummy.next;
   }
   var mergeSort = function (head, tail) {
         if (head === null) {
              return head;
         }
         if (head.next === tail) {
               head.next = null;
               return head;
         }
         var fast = head;
         var low = head;
         while (fast !== tail) {
              low = low.next;
              fast = fast.next;
              if (fast !== tail) {
                   fast = fast.next;
              }
         }
         var mid = low;
         return merge(mergeSort(head, mid), mergeSort(mid, tail));
  }
  var sortList = function(head) {
     return mergeSort(head, null);
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值