题目

题目来源:力扣(LeetCode)

给你一个整数数组 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]

方法一:快速排序

快速排序的主要思想是通过划分将待排序的序列分成前后两部分,其中前一部分的数据都比后一部分的数据要小,然后再递归调用函数对两部分的序列分别进行快速排序,以此使整个序列达到有序。

  1. /**
  2. * @param {number[]} nums
  3. * @return {number[]}
  4. */
  5. var sortArray = function(nums) {
  6. quickSort(nums, 0, nums.length - 1);
  7. return nums
  8. };
  9. const quickSort = (arr, left, right) => {
  10. // 只剩一个元素时,不用再进行排序
  11. if (left > right) return;
  12. let i = left, j = right;
  13. // 基准值
  14. const pivot = arr[i];
  15. while (i < j) {
  16. // 从右向左找到小的
  17. while (i < j && arr[j] >= pivot) {
  18. j--;
  19. }
  20. arr[i] = arr[j];
  21. // 从左向右找到大的
  22. while (i < j && arr[i] <= pivot) {
  23. i++
  24. }
  25. arr[j] = arr[i];
  26. }
  27. arr[i] = pivot;
  28. quickSort(arr, left, i - 1);
  29. quickSort(arr, i + 1, right);
  30. }

方法二:堆排序

堆排序的思想就是先将待排序的序列建成大根堆,使得每个父节点的元素大于等于它的子节点。此时整个序列最大值即为堆顶元素,我们将其与末尾元素交换,使末尾元素为最大值,然后再调整堆顶元素使得剩下的 n-1 个元素仍为大根堆,再重复执行以上操作我们即能得到一个有序的序列。

  1. /**
  2. * @param {number[]} nums
  3. * @return {number[]}
  4. */
  5. var sortArray = function (nums) {
  6. let len = nums.length
  7. const heapify = function (index) {
  8. const left = index * 2 + 1
  9. const right = index * 2 + 2
  10. let largest = index
  11. if (left < len && nums[left] > nums[largest]) {
  12. largest = left
  13. }
  14. if (right < len && nums[right] > nums[largest]) {
  15. largest = right
  16. }
  17. if (largest !== index) {
  18. swap(nums, index, largest)
  19. heapify(largest)
  20. }
  21. }
  22. const buildMaxHeap = function () {
  23. for (let i = len >> 1; i >= 0; i--) {
  24. heapify(i)
  25. }
  26. }
  27. buildMaxHeap()
  28. for (let i = len - 1; i >= 0; i--) {
  29. swap(nums, i, 0)
  30. len--
  31. heapify(0)
  32. }
  33. return nums
  34. }
  35. const swap = function (arr, i, j) {
  36. const temp = arr[i]
  37. arr[i] = arr[j]
  38. arr[j] = temp
  39. }

方法三:归并排序

归并排序利用了分治的思想来对序列进行排序。对一个长为 n 的待排序的序列,我们将其分解成两个长度为
n/2 的子序列。每次先递归调用函数使两个子序列有序,然后我们再线性合并两个有序的子序列使整个序列有序。

  1. /**
  2. * @param {number[]} nums
  3. * @return {number[]}
  4. */
  5. var sortArray = function (nums) {
  6. let len = nums.length
  7. const temp = []
  8. const merge = function (left, mid, right) {
  9. let p1 = left, p2 = mid + 1
  10. temp.length = 0
  11. while (p1 <= mid && p2 <= right) {
  12. temp.push(nums[p1] < nums[p2] ? nums[p1++] : nums[p2++])
  13. }
  14. while (p1 <= mid) {
  15. temp.push(nums[p1++])
  16. }
  17. while (p2 <= right) {
  18. temp.push(nums[p2++])
  19. }
  20. for (let i = left; i <= right; i++) {
  21. nums[i] = temp[i - left]
  22. }
  23. }
  24. const sort = function (left, right) {
  25. if (left >= right) return
  26. if (right - left === 1) {
  27. if (nums[left] > nums[right]) {
  28. swap(nums, left, right)
  29. }
  30. return
  31. }
  32. const mid = left + ((right - left) >> 1)
  33. sort(left, mid)
  34. sort(mid + 1, right)
  35. merge(left, mid, right)
  36. }
  37. sort(0, nums.length - 1)
  38. return nums
  39. };
  40. const swap = function (arr, i, j) {
  41. const temp = arr[i]
  42. arr[i] = arr[j]
  43. arr[j] = temp
  44. }