题目链接:https://leetcode-cn.com/problems/sort-an-array/submissions/

这是一道好题目,可以用来练习手撕各种排序算法,别直接调用api错过了这道好题哦!

目录

一、插入排序

(1)直接插入排序:超时

(2)折半插入排序:AC

(3)希尔排序:AC

二、交换排序

(1)冒泡排序:AC

(2)快速排序【递归】:AC

(3)快读排序【非递归】:AC

三、选择排序

(1)选择排序:AC

(2)堆排序:AC

四、归并排序

(1)归并排序:AC

五、JavaScript 内部 API

(1)直接调用API:AC


一、插入排序

(1)直接插入排序:超时

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {sort(nums);return nums;
};//插入排序
//稳定排序
//时间复杂度O(n2)
function sort(arr) {//首先把数组当做第一个元素为有序的序列,然后将后面的元素依次插入到合适的位置let i, j;for (i = 1; i < arr.length; i++) {if (arr[i] < arr[i - 1]) {let temp = arr[i]; //哨兵for (j = i - 1; temp < arr[j]; j--) {arr[j+1] = arr[j]; //直接往后覆盖移动,数据已经被哨兵保存}arr[j+1] = temp;}}
}

(2)折半插入排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {sort(nums);return nums;
};//稳定排序,之后小于才会引起移动,等于不会引起移动
//时间复杂度O(n2)
//折半插入排序
function sort(arr) {//先用折半查找的方式,找到待插入的位置,然后直接后移let i, j, low, high, mid;for (i = 1; i < arr.length; i++) {let temp = arr[i] //哨兵暂存low = 0; //默认i之前的所有元素已经是有序的high = i - 1;while (low <= high) {mid = ((high - low) > 2) + low;if (arr[mid] > temp) {high = mid - 1;} else {low = mid + 1;}}for(j = i-1;j >=high+1;j--){arr[j+1] = arr[j];}arr[high+1] = temp;}
}

(3)希尔排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {shellSort(nums);return nums;
};//不稳定排序
//时间复杂度O(n2)
//希尔排序
function shellSort(arr) {let len = arr.length;let gap = Math.floor(len / 2), ifor (gap; gap > 0; gap = Math.floor(gap / 2)) {for (i = gap; i < len; i++) {if (arr[i] < arr[i - gap]) {let temp = arr[i]for (j = i - gap; j >= 0 && temp < arr[j]; j -= gap) {arr[j + gap] = arr[j];}arr[j + gap] = temp;}}}
}

二、交换排序

(1)冒泡排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {bubbleSort(nums);return nums;
};//稳定排序
//时间复杂度最好O(n)
//冒泡排序
function bubbleSort(arr) {let flag; //表示本趟冒泡是否发生交换的标志for (let i = 0; i < arr.length - 1; i++) {flag = false;for (let j = arr.length - 1; j > i; j--) { //i之前的所有元素都是排好序的if (arr[j - 1] > arr[j]) {let temp = arr[j];arr[j] = arr[j - 1]arr[j - 1] = tempflag = true;}}if (flag === false) {  //本趟未发生交换,则说明已经有序,可以剪枝return;}}
}

(2)快速排序【递归】:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {let low = 0, high = nums.length - 1quickSort(nums, low, high);return nums;
};
//手撕快排
//时间复杂度最好O(ologn)
//不稳定排序
//找到枢值的准确排序位置
function partition(arr, low, high) {let pivot = arr[low]; //默认第一个元素为枢轴值while (low < high) {while (low < high && arr[high] >= pivot)--high;arr[low] = arr[high];while (low < high && arr[low] <= pivot)++low;arr[high] = arr[low];}arr[low] = pivot;return low;
}function quickSort(arr, low, high) {if (low < high) {let pivotPos = partition(arr, low, high);quickSort(arr, low, pivotPos - 1);quickSort(arr, pivotPos + 1, high);}
}

(3)快读排序【非递归】:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {let stack = []quickSort(nums, stack);return nums;
};
//手撕快排-非递归
function quickSort(arr, stack) {let l = 0,r = arr.length-1;stack.push(l);stack.push(r);while(stack.length !== 0){let rr = stack.pop();r = rr;let ll = stack.pop();l = ll;let pivot = arr[ll];if(ll < rr){while(ll < rr){while(ll < rr && arr[rr] >= pivot) rr--;arr[ll] = arr[rr];while(ll < rr && arr[ll] <= pivot) ll++;arr[rr] = arr[ll];}arr[ll] = pivot;stack.push(l);stack.push(ll-1);stack.push(ll+1);stack.push(r);}}
}

三、选择排序

(1)选择排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {selectSort(nums);return nums;
};//不稳定排序
//时间复杂度O(n2)
//选择排序
function selectSort(arr) {let min;for (let i = 0; i < arr.length - 1; i++) { //只需要比较n-1趟min = i;for (let j = i + 1; j < arr.length; j++) {if(arr[j] < arr[min])min = j;}if(min !== i){let tmp = arr[min];arr[min] = arr[i];arr[i] = tmp;}}
}

(2)堆排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {nums.unshift(-1);return HeapSort(nums);
};//不稳定排序
//时间复杂度最好O(nlog2n)
//堆排序
/*
* 堆是一个完全二叉树,满足任意一个非叶节点的值都不大于其左右孩子节点的值(小顶堆)
*                                       不小于                大顶堆
* 思想:将无序序列调节成一个堆,然后从堆中选择堆顶元素的值,将这个值加入有序序列,无序序列减少一个值
*
* 调节顺序:由下至上,由右至左
* */
function HeapSort(arr) {let len = arr.length - 1;let ans = []BuildMinHeap(arr); //建立小顶堆for (let i = len; i > 0; i--) {let tmp = arr[1];arr[1] = arr[i];arr[i] = tmp;ans.push(arr[i]);AdjustDown(arr, 1, i - 1);}return ans;
}//建堆,反复调整
function BuildMinHeap(arr) {let len = arr.length - 1for (let i = Math.floor(len / 2); i > 0; i--) {  //Math.floor(len / 2) 第一个可能需要调整的非叶子节点AdjustDown(arr, i, len)}
}//调整一次,k为开始检查点
function AdjustDown(arr, k, len) {arr[0] = arr[k];for (let i = 2 * k; i <= len; i *= 2) {  //2 * k 为其左孩子if (i < len && arr[i] > arr[i + 1])i++; //找到左右孩子中值更大的那个if (arr[0] <= arr[i]) {break   //树顶已经最小} else {arr[k] = arr[i];k = i;}}arr[k] = arr[0];
}

四、归并排序

(1)归并排序:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {mergeSort(nums, 0, nums.length - 1);return nums;
};//稳定排序
//时间复杂度最好O(nlog2n)
//归并排序
function mergeSort(arr, low, high) {if (low < high) { //至少保证有2个元素,使其归并合一let mid = Math.floor((low + high) / 2);mergeSort(arr, low, mid); //递归分组mergeSort(arr, mid + 1, high);merge(arr, low, mid, high); //两两合并}
}function merge(arr, low, mid, high) {let tmpArr = []let pos = low, i, jfor (let k = low; k <= high; k++) {tmpArr[k] = arr[k]  //元素复制,左右归并}for (i = low, j = mid + 1; i <= mid && j <= high; pos++) {if (tmpArr[i] <= tmpArr[j]) {arr[pos] = tmpArr[i++]} else {arr[pos] = tmpArr[j++]}}while (i <= mid) arr[pos++] = tmpArr[i++];while (j <= high) arr[pos++] = tmpArr[j++];
}

五、JavaScript 内部 API

(1)直接调用API:AC

/*** @param {number[]} nums* @return {number[]}*/
var sortArray = function(nums) {return nums.sort((a,b)=>a-b)
};

除了直接插入排序超时,其他都可以执行,小伙伴们练手吧~

LeetCode912. 排序数组(JavaScript手撕各种排序算法)相关推荐

  1. 手撕七大排序 (二)

    手撕七大排序 (二) 交换排序 一. 冒泡排序 1. 单趟冒泡排序 2. 多趟排序 二. 快速排序 选择排序 一. 选择排序 1. 单趟选择排序 2. 完整选择排序 二. 堆排序 交换排序 一. 冒泡 ...

  2. 为什么处理排序数组要比处理未排序数组快?

    这是一段C ++代码,显示了一些非常特殊的行为. 出于某些奇怪的原因,奇迹般地对数据进行排序使代码快了将近六倍: #include <algorithm> #include <cti ...

  3. 万字手撕七大排序(代码+动图演示)

    万字拿捏七大排序 1.排序的概念及其运用 1.1排序的概念 1.2 排序的运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2直接插入排序 2.1 ...

  4. 常见js手撕题及算法总结

    文章目录 实现一下观察者模式 实现一下工厂模式 实现一下单例模式 设计一个lazyMan,实现以下功能: 实现一个简单的EventEmitter 手撕实现原生js的一些方法(call.apply.bi ...

  5. 手撕Twitter推荐算法

    Twitter近期开源了其推荐系统源码[1,2,3],截止现在已经接近36k star.但网上公开的文章都是blog[1]直译,很拗口,因此特地开个系列系统分享下.系列涵盖: Twitter整体推荐系 ...

  6. c++排序数组下标_看动画学算法之:排序 - 基数排序

    简介 之前的文章我们讲了count排序,但是count排序有个限制,因为count数组是有限的,如果数组中的元素范围过大,使用count排序是不现实的,其时间复杂度会膨胀. 而解决大范围的元素排序的办 ...

  7. 手撕自动驾驶算法——多目标追踪:imm交互式多模型

    文章目录 基本原理 流程图 公式推导 Mixing Prediction Updates Combination 基本原理 状态估计问题依赖于对象运动模型来预测和更新对象状态.然而,在城市情况下,被跟 ...

  8. 手撕自动驾驶算法——无迹卡尔曼滤波(UKF)

    文章目录 1. 简介 2. CTRV运动模型 2.1 CTRV的目标状态量: 2.2 CTRV的状态转移函数: 2.3 CTRV Process Noise 3. Prediction 3.1 Gen ...

  9. 手撕自动驾驶算法——IMU测量模型、运动模型、误差模型

    目录 IMU测量模型 IMU运动模型 旋转量求导 科氏加速度 IMU 误差模型 确定性误差 确定性误差误差标定 六面法标定加速度 六面法标定陀螺仪 温度相关的参数标定 随机误差 高斯白噪声与随机游走 ...

最新文章

  1. 零基础入门学习Python(31)-异常处理2-try语句
  2. linux定时执行python脚本_linux定时执行python脚本的方法以及失败不执行的处理方法...
  3. 04.ARP:地址解析协议
  4. python中的input函数怎么用_python input()函数怎么用,_Python_ 少侠科技
  5. 聚类(序)——监督学习与无监督学习
  6. jQuery中eq和get的区别
  7. webflux切面拦截权限,webflux整合aop,webflux获取request
  8. 手写及场景文字分析与识别的一些新尝试
  9. 【zz】Matlab 二值图像形态学函数 bwmorph
  10. 使用 vs 2008 宏制作自动注释工具
  11. 仿真文件的写法(以四位全加器为例)
  12. php当前页面删除处理,php删除记录同时刷新当前页面的实现代码
  13. Linux wpa_cli 调试方法
  14. 116 Python GIL全局解释器锁
  15. 思科CCNA电子教程
  16. 供应链金融三种模式介绍及对比
  17. 小程序微信商家API V3对接转账到零钱(JAVA)
  18. 总账科目往来批量导入程序
  19. 【直播报名】Location Cache 模块浅析及 OCP 监控、报警详解
  20. 电脑小问题七:台式机连接无线网络+无线网卡

热门文章

  1. 荧光标记肿瘤细胞解决方案
  2. PPT在线预览 转换为图片实现方案 Apache POI 实现时踩坑:含嵌入文件ppt转换报错 ArrayStoreException
  3. 公众号redirect_url配置_Niushop微信支付配置、微信退款配置、微信转账配置操作流程...
  4. MTK平台DDR降频(调整频率)的方法
  5. 第三方网站应用微信登录开发指南
  6. UVA1149 装箱 Bin Packing 题解
  7. mysql不停機添加節點_MySQL 5.7主从不停机添加新从库
  8. 一个鹅厂码农的深圳买房笔记,7年时间从月薪1万到净资产2100万。。。
  9. 我为什么要写博客,写博客的意义是什么
  10. PostgreSQL 报ERROR: column c.relhasoids does not exist