LeetCode912. 排序数组(JavaScript手撕各种排序算法)
题目链接: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. 单趟冒泡排序 2. 多趟排序 二. 快速排序 选择排序 一. 选择排序 1. 单趟选择排序 2. 完整选择排序 二. 堆排序 交换排序 一. 冒泡 ...
- 为什么处理排序数组要比处理未排序数组快?
这是一段C ++代码,显示了一些非常特殊的行为. 出于某些奇怪的原因,奇迹般地对数据进行排序使代码快了将近六倍: #include <algorithm> #include <cti ...
- 万字手撕七大排序(代码+动图演示)
万字拿捏七大排序 1.排序的概念及其运用 1.1排序的概念 1.2 排序的运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2直接插入排序 2.1 ...
- 常见js手撕题及算法总结
文章目录 实现一下观察者模式 实现一下工厂模式 实现一下单例模式 设计一个lazyMan,实现以下功能: 实现一个简单的EventEmitter 手撕实现原生js的一些方法(call.apply.bi ...
- 手撕Twitter推荐算法
Twitter近期开源了其推荐系统源码[1,2,3],截止现在已经接近36k star.但网上公开的文章都是blog[1]直译,很拗口,因此特地开个系列系统分享下.系列涵盖: Twitter整体推荐系 ...
- c++排序数组下标_看动画学算法之:排序 - 基数排序
简介 之前的文章我们讲了count排序,但是count排序有个限制,因为count数组是有限的,如果数组中的元素范围过大,使用count排序是不现实的,其时间复杂度会膨胀. 而解决大范围的元素排序的办 ...
- 手撕自动驾驶算法——多目标追踪:imm交互式多模型
文章目录 基本原理 流程图 公式推导 Mixing Prediction Updates Combination 基本原理 状态估计问题依赖于对象运动模型来预测和更新对象状态.然而,在城市情况下,被跟 ...
- 手撕自动驾驶算法——无迹卡尔曼滤波(UKF)
文章目录 1. 简介 2. CTRV运动模型 2.1 CTRV的目标状态量: 2.2 CTRV的状态转移函数: 2.3 CTRV Process Noise 3. Prediction 3.1 Gen ...
- 手撕自动驾驶算法——IMU测量模型、运动模型、误差模型
目录 IMU测量模型 IMU运动模型 旋转量求导 科氏加速度 IMU 误差模型 确定性误差 确定性误差误差标定 六面法标定加速度 六面法标定陀螺仪 温度相关的参数标定 随机误差 高斯白噪声与随机游走 ...
最新文章
- 零基础入门学习Python(31)-异常处理2-try语句
- linux定时执行python脚本_linux定时执行python脚本的方法以及失败不执行的处理方法...
- 04.ARP:地址解析协议
- python中的input函数怎么用_python input()函数怎么用,_Python_ 少侠科技
- 聚类(序)——监督学习与无监督学习
- jQuery中eq和get的区别
- webflux切面拦截权限,webflux整合aop,webflux获取request
- 手写及场景文字分析与识别的一些新尝试
- 【zz】Matlab 二值图像形态学函数 bwmorph
- 使用 vs 2008 宏制作自动注释工具
- 仿真文件的写法(以四位全加器为例)
- php当前页面删除处理,php删除记录同时刷新当前页面的实现代码
- Linux wpa_cli 调试方法
- 116 Python GIL全局解释器锁
- 思科CCNA电子教程
- 供应链金融三种模式介绍及对比
- 小程序微信商家API V3对接转账到零钱(JAVA)
- 总账科目往来批量导入程序
- 【直播报名】Location Cache 模块浅析及 OCP 监控、报警详解
- 电脑小问题七:台式机连接无线网络+无线网卡
热门文章
- 荧光标记肿瘤细胞解决方案
- PPT在线预览 转换为图片实现方案 Apache POI 实现时踩坑:含嵌入文件ppt转换报错 ArrayStoreException
- 公众号redirect_url配置_Niushop微信支付配置、微信退款配置、微信转账配置操作流程...
- MTK平台DDR降频(调整频率)的方法
- 第三方网站应用微信登录开发指南
- UVA1149 装箱 Bin Packing 题解
- mysql不停機添加節點_MySQL 5.7主从不停机添加新从库
- 一个鹅厂码农的深圳买房笔记,7年时间从月薪1万到净资产2100万。。。
- 我为什么要写博客,写博客的意义是什么
- PostgreSQL 报ERROR: column c.relhasoids does not exist