【手撕算法】排序

目录

      • 1 插入排序
      • 2 堆排序
      • 3 归并排序
      • 4 快速排序
      • 5 冒泡排序
      • 6 选择排序

1 插入排序

时间复杂度O(n2)O(n^2)O(n2) 空间复杂度 O(1) 稳定

从第一个元素开始,认为左边的序列是有序的,从有序部分的最后一个向前比较,如果当前元素小于有序部分就交换,否则比较下一个元素。

function insertMerge(arr) {for(let i = 1; i < arr.length; i++) {let target = ifor (let j = i-1; j >= 0; j--) {if (arr[target] < arr[j]) { // 无序 交换元素[arr[target], arr[j]] = [arr[j], arr[target]]target = j // 交换之后target变为j} else {break // 有序 直接i++}}}return arr
}
let arr = [1,5,2,4,3,6,8,7]
console.log(insertMerge(arr));

2 堆排序

时间复杂度O(n)O(n)O(n) 空间复杂度 O(1) 不稳定

先建堆,然后每次让数组的最后一个元素和第一个元素进行交换,交换之后调整堆。注意每一轮交换之后找到一个最大值放在了原数组的末尾,下次交换这个元素不参与,相当于原数组长度-1。

建堆是从最后一个非叶子节点开始也就是 (len/2-)1,依次向上调整

调整的过程是拿目标节点和两个子节点中最大的值比较,如果子节点大就交换,目标节点变成较大的子节点,否则,已符合堆结构,进行下一轮调整。

/*** 完全二叉树的最后一个非叶子节点是 Math.floor(len/2)-1* 孩子节点的 2*i+1 和 2*i+2*/
function heapSort(arr) {// 建堆 找到一个最大值createHeap(arr, 0, arr.length)// console.log(arr);// 每一轮跳过一个最后的最大值for (let i = arr.length-1; i >= 0; i--) {// 每次交换第一个元素和该轮数组的最后一个元素// 最后一个元素是最大值 下一轮只需要比较之前的序列 最后一个元素变成了i-1[arr[i], arr[0]] = [arr[0], arr[i]]// i 是数组的长度adjust(arr, 0, i)}return arr
}
function createHeap(arr) {const len = arr.length// 从最后一个非叶子节点开始调整const start = Math.floor(len/2)-1for(let i = start; i >= 0; i--) {adjust(arr, i, len)}
}
function adjust(arr, target, len) {for (let i = 2*target+1; i < len; i = i*2+1) {if (i + 1 < len && arr[i+1] > arr[i]) {i = i + 1}if (arr[target] < arr[i]) {[arr[target], arr[i]] = [arr[i], arr[target]]target = i} else {break}}
}let arr = [1,3,2,5,3,6,2,0]
console.log(heapSort(arr))

3 归并排序

时间复杂度O(nlogn) 空间复杂度O(n) 稳定

  1. 分割
    将数组从分成左右两个数组,然后递归的分割,知道数组的长度小于2
  2. 合并
    当左右两个数组有序的时候,合并两个数组。创建一个空数组temp,比较左右两边的数组,小值加入到temp中。若左右数组有一个为空,那么此时另一个数组一定大于temp中的所有元素,直接将其所有元素加入temp。
    然后将tmp的值一一传递给原数组
function mergeSort(arr, left, right, tmp) {if (left >= right) return arrconst mid = Math.floor((left+right)/2)mergeSort(arr, left, mid, tmp)mergeSort(arr, mid+1, right, tmp)merge(arr, left, right, tmp)return arr
}function merge(arr, left, right, tmp) {const mid = Math.floor((left+right)/2)let leftIndex = leftlet rightIndex = mid + 1let tmpIndex = 0while (leftIndex <= mid && rightIndex <= right) {if (arr[leftIndex] < arr[rightIndex]) {tmp[tmpIndex++] = arr[leftIndex++]} else {tmp[tmpIndex++] = arr[rightIndex++]}}while (leftIndex <= mid) {tmp[tmpIndex++] = arr[leftIndex++]}while (rightIndex <= right) {tmp[tmpIndex++] = arr[rightIndex++]}tmpIndex = 0for (let i = left; i <= right; i++) {arr[i] = tmp[tmpIndex++]}
}let arr = [3,4,2,1,5,0]
mergeSort(arr, 0, arr.length-1, [])
console.log(arr)

4 快速排序

时间复杂度:平均O(nlogn),最坏O(n2)O(n^2)O(n2),实际上大多数情况下小于O(nlogn)

空间复杂度:O(logn)(递归调用消耗)

快速排序是每次找到一个基准元素,左右两边分别和基准元素比较,如果左边元素小于基准元素,左指针向右移动,如果右边元素大于基元素,右指针向左移动。否则,就交换左右两边的元素。当左右指针相遇,相遇处即是基准元素所在的位置,将基准元素交换到该位置。基准元素切分出了左右两边,左边都比基准元素小,右边都比基准元素大。

function quickSort(arr, left, right) {if (left >= right) returnlet i = left, j = right, pivot = arr[left]while (i < j) {while (i < j && arr[j] >= pivot) {j--}while (i < j && arr[i] <= pivot) {i++}swap(arr, i, j)}swap(arr, left, i)quickSort(arr, left, i-1)quickSort(arr, i+1, right)
}function swap(arr, i, j) {const tmp = arr[i]arr[i] = arr[j]arr[j] = tmp
}const arr = [3,2,4,1,5,6,8]
quickSort(arr, 0, arr.length-1)
console.log(arr)

5 冒泡排序

时间复杂度O(n2)O(n^2)O(n2) 空间复杂度O(1) 不稳定
每次将一个最大值沉底,下一次比较不考虑沉底的元素

function bubble(arr) {const len = arr.length// 将第i个最大值沉底for (let i = 0; i < len; i++) {// 排除沉底元素 进行比较for (let j = 0; j < len-i-1; j++) {// 比较的是内层循环if (arr[j+1] < arr[j]) {[arr[j+1], arr[j]] = [arr[j], arr[j+1]]}}}return arr
}
const arr = [4,5,2,1,3]
bubble(arr)
console.log(arr)

6 选择排序

时间复杂度O(n2)O(n^2)O(n2) 空间复杂度O(1) 不稳定

每次选出最小的元素放在未排序的部分的首位

/*** 每次选出最小的元素放在首位*/
function selectSort(arr) {const len = arr.lengthlet minIndexfor (let i = 0; i < len; i++) {minIndex = ifor (let j = i+1; j < len; j++) {if(arr[minIndex] > arr[j]) {minIndex = j}}[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]}
}const arr = [1,3,2,1,5,6,7]
selectSort(arr)
console.log(arr)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mikechen谈技术人成长的三大原则

“ 我自己是工程师出身&#xff0c;一路就像游戏打怪一样&#xff0c;不断去突破自己的职能舒适区&#xff0c;技术这条路我用了整整10年去把它全部打通&#xff0c;这些经验看似平淡&#xff0c;作为一个过来人&#xff0c;在你每一次新的选择的时候&#xff0c;你就会发现它…

最新进展 | 深度学习在天气预测中的应用

谷歌研究员提出使用机器学习方法预测未来短时间内的天气。此方法虽然处于早期发展阶段&#xff0c;但效果已经优于传统模型。 前言 天气总是会或轻或重地影响人们的日常生活&#xff0c;而天气预报的准确性会极大影响人们应对天气的方式。天气预报可以告知人们是否应当选取一条…

快速上手笔记,PyTorch模型训练实用教程(附代码)

前言自 2017 年 1 月 PyTorch 推出以来&#xff0c;其热度持续上升&#xff0c;一度有赶超 TensorFlow 的趋势。PyTorch 能在短时间内被众多研究人员和工程师接受并推崇是因为其有着诸多优点&#xff0c;如采用 Python 语言、动态图机制、网络构建灵活以及拥有强大的社群等。因…

领域应用 | 中医临床术语系统V2.0在线发布啦!

本文转载自公众号&#xff1a;中医药知识组织与标准。中医临床术语系统V2.0在线发布中医临床术语系统&#xff08;Traditional Chinese Medicine Clinical Terminological Systems, TCMCTS&#xff09;是由中国中医科学院中医药信息研究所研制的&#xff0c;用来描述健康状况和…

【手撕算法】字符串

文章目录1 求最长公共前缀1.1 暴力法1.2 分治法2 最长回文子串2.1 暴力法1 求最长公共前缀 1.1 暴力法 以第一个为基准&#xff0c;取其前缀&#xff0c;与其他字符串依次比较&#xff0c;如果全部相同&#xff0c;就更新res。res指向公共前缀的末尾。 var longestCommonPre…

NLP Subword三大算法原理:BPE、WordPiece、ULM

Subword算法如今已经成为了一个重要的NLP模型性能提升方法。自从2018年BERT横空出世横扫NLP界各大排行榜之后&#xff0c;各路预训练语言模型如同雨后春笋般涌现&#xff0c;其中Subword算法在其中已经成为标配。且与传统空格分隔tokenization技术的对比有很大的优势~~ E.g. 模…

【小程序】微信小程序开发实践

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/diandianxiyu/article/details/53068012 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck…

技术人如何提升自己的核心竞争力

互联网行业是一个发展非常快&#xff0c;变化也快的行业&#xff0c;在这个行业&#xff0c;总是让人感觉既兴奋又不安。 兴奋的是你总能看到无数新奇的事物&#xff0c;甚至亲身参与到一场变革中去&#xff0c;而不安的则是&#xff0c;任凭你如何NB&#xff0c;你也无法保证哪…

AAAI 2018经典论文获奖者演讲:本体论的昨天和今天

本文转自公众号&#xff1a;AI科技评论。AI 科技评论按&#xff1a;正在美国新奥尔良召开的 AAAI 2018 的经典论文奖颁给了《Algorithm and Tool for Automated Ontology Merging and Alignment》。这篇论文发表在 2000 年的第 17 届 AAAI 大会上。这次颁奖是为了表彰这篇论文在…

ICLR2020 | 如何判断两个神经网络学到的知识是否一致

人工智能顶会 ICLR 2020 将于 4 月 26 日于埃塞俄比亚首都亚的斯亚贝巴举行。在最终提交的 2594 篇论文中&#xff0c;有 687 篇被接收&#xff0c;接收率为 26.5%。本文介绍了上海交通大学张拳石团队的一篇接收论文——《Knowledge Consistency between Neural Networks and B…

7张图学会SQL

第1周&#xff1a;SQL入门 学习SQL语句的书写语法和规则从零学会SQL&#xff1a;入门​www.zhihu.com 第2周&#xff1a;查询基础 Select查询语句是SQL中最基础也是最重要的语句&#xff0c;这周我们就来利用Select来对表中的数据进行查询。从零学会SQL&#xff1a;简单查询​w…

大公司稳定工作和创业之间如何选择?

“ 是留在大公司&#xff0c;还是加入小型创业公司&#xff0c;还是自己创业&#xff0c;面对房价每年高涨的趋势&#xff0c;面对未来的不确定&#xff0c;应该怎样选择。 作为一个亲历者&#xff0c;希望你看完后能有所启发。 本文作者&#xff0c;陈睿 优知学院创始人 优知…

论文浅尝 |「知识表示学习」专题论文推荐

本文转载自公众号&#xff1a;PaperWeekly。本期论文清单来自清华大学博士生韩旭和北师大本科生曹书林&#xff0c;涵盖了近年知识表示学习方向的重要论文。[ 综述类 ]■ 论文 | Representation Learning: A Review and New Perspectives■ 链接 | https://www.paperweekly.sit…

如何选择一家公司

不管是刚毕业的大学生还是工作几年的职场朋友&#xff0c;每个人都会面临选择公司和行业的困扰&#xff0c;我也相信每个人都还记忆犹新你的第一份工作以及让你无比难忘的一家公司。有时候我们也盲目的所求&#xff0c;其实&#xff0c;偶尔停下来思考下你真想去的地方&#xf…

LightGBM最强解析,从算法原理到代码实现~

1 LightGBM简介 GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型&#xff0c;其主要思想是利用弱分类器&#xff08;决策树&#xff09;迭代训练以得到最优模型&#xff0c;该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛&#xf…

数据分析师基本技能——SQL

我们做数据分析工作时&#xff0c;多数数据来源于数据库&#xff0c;SQL非常方便我们访问和查询数据库。 SQL 作为数据分析师的基本技能&#xff0c;那么需要掌握哪些SQL核心技能 理解数据库SQL基础重点知识&#xff1a;查询&#xff0c;更新&#xff0c;提取&#xff0c;插入&…

论文浅尝 | 基于置信度的知识图谱表示学习框架

本文转载自公众号&#xff1a;PaperWeekly。作者丨谢若冰单位丨腾讯微信搜索应用部研究方向丨知识表示学习知识图谱被广泛地用来描述世界上的实体和实体之间的关系&#xff0c;一般使用三元组&#xff08;h,r,t&#xff09;&#xff08;head entity, relation, trail entity&am…

史上最强Java架构师的13大技术能力讲解! | 附架构师能力图谱

从程序员进阶成为架构师&#xff0c;并非一蹴而就&#xff0c;需要系统化、阶段性地学习&#xff0c;在实战项目中融会贯通&#xff0c;这如同打怪通关&#xff0c;我们得一关一关突破&#xff0c;每攻破一个关口&#xff0c;就能得到更精良的装备&#xff0c;技能值也随之不断…

写给运营同学和初学者的SQL入门教程

作者简介 多肉&#xff0c;饿了么资深python工程师。曾在17年担任饿了么即时配送众包系统的研发经理&#xff0c;这篇文章最早的版本就诞生于那段时间&#xff0c;目前负责配送相关业务系统的整体稳定性建设。个人比较喜欢c和python&#xff0c;最近有点迷rust&#xff0c;同时…

强化学习,路在何方?

▌一、深度强化学习的泡沫 2015年&#xff0c;DeepMind的Volodymyr Mnih等研究员在《自然》杂志上发表论文Human-level control through deep reinforcement learning[1]&#xff0c;该论文提出了一个结合深度学习&#xff08;DL&#xff09;技术和强化学习&#xff08;RL&…