刷题60—排序数组
97.排序数组
题目链接
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-an-array
题目描述
给定一个整数数组 nums,将该数组升序排列。
示例 1:
输入:[5,2,3,1]
输出:[1,2,3,5]
示例 2:
输入:[5,1,1,2,0,0]
输出:[0,0,1,1,2,5]
提示:
1 <= A.length <= 10000
-50000 <= A[i] <= 50000
关键技术
算法 | 稳定性 | 时间复杂度 | 空间复杂度 | 执行用时 | 内存消耗 |
自带sort排序 | × | n·log(n) | log(n) | 136ms | 42M |
冒泡排序 | √ | n² | 1 | 4988ms | 40.4M |
选择排序 | × | n² | 1 | 2220ms | 40.5M |
插入排序 | √ | n² | 1 | 888ms | 40.4M |
希尔排序 | × | n·log(n) | 1 | 116ms | 40.2M |
快速排序 | × | n·log(n) | log(n) | 200 ms | 54.1M |
题目分析
法一:sort 函数:v8中的sort()在10以内是插入排序,其余是快排。
1 2 3 4 5 6 7 8 | /** * @param {number[]} nums * @return {number[]} */ var sortArray = function (nums) { nums.sort((a,b)=>a-b); return nums; }; |
法二:冒泡排序:比较相邻的元素,从开始第一对比到结尾的最后一对,如果前一个比后一个大,交换位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /** * @param {number[]} nums * @return {number[]} */ //冒泡排序 var sortArray = function (nums) { let n = nums.length; if (n < 2){ return nums; } for ( let i=0;i<n;i++){ for ( let j=0;j<n-i-1;j++){ if (nums[j+1] < nums[j]) { let temp = nums[j+1]; nums[j+1] = nums[j]; nums[j] = temp; } } } return nums; }; |
法三:选择排序:从数组中选择最小的元素,将它与数组中第一个元素交换位置,再从数组剩下的元素中选择出最小的元素,与数组第二个位置交换顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * @param {number[]} nums * @return {number[]} */ //选择排序 var sortArray = function (nums) { let n = nums.length; if (n < 2){ return nums; } for ( let i=0;i<n;i++){ let min = i; for ( let j=i;j<n;j++){ if (nums[j] < nums[min]) { min = j; } } let temp = nums[min]; nums[min] = nums[i]; nums[i] = temp; } return nums; }; |
法四:插入排序:每次都将当前元素插入到左侧已经排序的数组中,使得插入之后左侧数组依然有序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * @param {number[]} nums * @return {number[]} */ //插入排序 var sortArray = function (nums) { let n = nums.length; if (n < 2){ return nums; } for ( let i=1;i<n;i++){ let temp = nums[i]; let j = i-1; //默认已排序的元素 while (j>=0 && nums[j]>temp){ //在已排序好的队列中从后向前扫描 nums[j+1] = nums[j]; //已排序的元素大于新元素,将该元素移动到下一个位置 j--; } nums[j+1] = temp; } return nums; }; |
法五:希尔排序:使用插入排序,对间隔h的序列进行排序。通过不断减小h,最后令h=1,就可以使得整个数组是有序的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /** * @param {number[]} nums * @return {number[]} */ //希尔排序 var sortArray = function (nums) { let n = nums.length; if (n < 2){ return nums; } // 初始步数 let gap = parseInt(n/2); // 逐渐缩小步数 while (gap){ // 从第gap个元素开始遍历 for ( let i=gap;i<n;i++){ // 逐步和其前面其他的组成员进行比较和交换 for ( let j=i-gap;j>=0;j-=gap){ if (nums[j] > nums[j+gap]){ [nums[j],nums[j+gap]] = [nums[j+gap],nums[j]]; } else { break ; } } } gap = parseInt(gap/2); } return nums; }; |
法六:快速排序:通过切分元素将数组分成两个子数组,左子数组<=切分元素,右子数组>=切分元素,将两个子数组排序,也就是将整个数组排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** * @param {number[]} nums * @return {number[]} */ //快速排序 var sortArray = function (nums) { //如果数组<=1,则直接返回 let n = nums.length; if (n < 2){ return nums; } let centerIndex = parseInt(n/2); //找基准,并把基准从原数组删除 let centerNum = nums.splice(centerIndex,1)[0]; //定义左右数组 let left = []; let right = []; //比基准小的放在left,比基准大的放在right for ( let i=0;i<nums.length;i++){ if (nums[i] <= centerNum){ left.push(nums[i]); } else { right.push(nums[i]); } } //递归 return sortArray(left).concat([centerNum],sortArray(right)); }; |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步