[路飞]_LeetCode_912. 排序数组

178 阅读2分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

题目

给你一个整数数组 nums,请你将该数组升序排列。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

来源:力扣(LeetCode)leetcode-cn.com/problems/so…

解题思路

排序数组有很多方式,可以用冒泡排序、选择排序、快速排序、二路归并排序等等,这里我们选择二路归并排序。

二路归并采用了分治的思想,把数组从中间分开,变成两个子数组,再把子数组拆分两个子数组,重复操作多次,直到每个数组中只有一个元素,然后再进行线性合并。

线性合并步骤:

  • 循环遍历左右两个数组,循环变量为 i、j;
  • 左边数组第 i 个元素和右边数组第 j 个元素对比,较小的元素加到结果中,并且变量加 1,只要有一边变量达到数组长度则结束循环;
  • 把未结束的数组剩余部分继续加到结果中;

二路归并排序的时间复杂度为O(nlogn)。执行过程如下:

image.png

代码实现

var sortArray = function (nums) {
        //使用二路归并排序对数组进行排序
	return mergeSort(nums, 0, nums.length - 1)
};

var mergeSort = function (nums, left, right) {
	//如果左边下标等于右边下标,说明已经不能再拆分,返回[nums[left]]
	if (left === right) return [nums[left]]

	//左边加右边右移1位得到中间位置
	const mid = (left + right) >> 1

	//将左边部分进行排序
	const leftArr = mergeSort(nums, left, mid)

	//将右边部分进行排序
	const rightArr = mergeSort(nums, mid + 1, right)

	//最后合并左边和右边排序的结果
	return merge(leftArr, rightArr)
};

var merge = function (left, right) {
	const ans = []
	let i = j = 0
	let llen = left.length
	let rlen = right.length

	//对左右两个数组进行线性合并
	while (i < llen && j < rlen) {
		if (left[i] <= right[j]) {
			ans.push(left[i++])
		} else {
			ans.push(right[j++])
		}
	}

	//如果左边还没合并完,则把剩下的部分继续合并到结果中
	while (i < llen) {
		ans.push(left[i++])
	}

	//如果右边还没合并完,则把剩下的部分继续合并到结果中
	while (j < rlen) {
		ans.push(right[j++])
	}

	return ans
};

如有错误欢迎指出,欢迎一起讨论!