【leetcode】手撕排序算法,力扣912题的7大排序算法代码归总(纯代码)

【leetcode】手撕排序算法,力扣912题的7大排序算法代码归总(纯代码)


前言

🌟🌟本期讲解关于力扣的几篇题解的详细介绍~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-ZEEKLOG博客

🔥 你的点赞就是小编不断更新的最大动力                                       

🎆那么废话不多说直接开整吧~~

 

目录

📚️1.超时排序

🚀1.1冒泡排序

​编辑

🚀1.2插入排序

🚀1.3选择排序

📚️2.通过排序

🚀2.1希尔排序

🚀2.2堆排序

🚀2.3分治排序

🚀 2.4归并排序

📚️3.总结

 

——前言:本期小编主要是代码的展示,对于每个算法在之前就已经讲解过,那么那就展示吧~~

——分治归并算法讲解:【leetcode】拆解与整合:分治并归的算法逻辑-ZEEKLOG博客 

——基础排序算法讲解:【数据结构】关于冒泡排序,选择排序,插入排序,希尔排序,堆排序你到底了解多少???(超详解)_堆排序、希尔排序、冒泡排序、选择排序-ZEEKLOG博客

📚️1.超时排序

这里的超时就是针对于912题进行的测试~~~

🚀1.1冒泡排序

直接上代码:

class Solution { public int[] sortArray(int[] nums) { //冒泡排序 for(int i = 0; i < nums.length; i++){ for(int j = 0 ; j < nums.length - 1 - i; j ++){ if(nums[j + 1] < nums[j]){ swap(nums,j+1,j); } } } return nums; } public void swap(int[] nums,int i,int j){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } }
大体思路:就是不断遍历我们的数组,然后将最大的值确认到我们的数组最后方,总共要循环数组长度大小次数;

1. 冒泡排序是一种非常容易理解的排序

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:稳定

运行结果: 

🚀1.2插入排序

代码如下:

class Solution { public int[] sortArray(int[] nums) { //插入排序 for(int j = 1; j < nums.length; j++){ int temp = nums[j]; for(int i = j - 1; i >= 0 ; i--){ if(nums[i] > temp){ nums[i + 1] = nums[i]; }else{ break; } nums[i] = temp; } } return nums; } }
大体思路:就是在遍历的时候,将遍历区间内的最小数移动到数组最左端;就像是从左向右理扑克牌一样

1. 元素集合越接近有序,直接插入排序算法的时间效率越高


2. 时间复杂度:

最坏情况:O(N^2)   (5    4    3    2    1)完全逆序

最好情况:O(N)       (1    2    3    4    5)完全顺序


3. 空间复杂度:O(1),它是一种稳定的排序算法


4. 稳定性:稳定

 运行结果:

🚀1.3选择排序

 代码如下:

class Solution { public int[] sortArray(int[] nums) { //选择排序 for(int i = 0;i < nums.length; i++){ int midIndex = i; for(int j = i + 1; j < nums.length;j ++){ if(nums[midIndex] > nums[j]){ midIndex = j; } } //与我们的第一个数值进行交换操作 int temp = nums[midIndex]; nums[midIndex] = nums[i]; nums[i] = temp; } return nums; } }
 大体思路:即遍历完数组确定最小元素下标,与第一个数组第一个值进行交换;

1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用


2. 时间复杂度:O(N^2)(不管排序情况咋样)


3. 空间复杂度:O(1)


4. 稳定性:不稳定

运行结果:

 

📚️2.通过排序

🚀2.1希尔排序

代码如下所示:

class Solution { public int[] sortArray(int[] nums) { int gap = nums.length; while(gap >= 1){ gap /= 2; shell(nums,gap); } return nums; } //希尔排序,优化插入排序 public void shell(int[] nums,int gap){ for(int j = gap ; j < nums.length; j++){ int temp = nums[j]; for(int i = j - gap ; i >= 0 ; i-=gap){ if(nums[i] > temp){ nums[i + gap] = nums[i]; }else{ break; } nums[i] = temp; } } } }
大体思路:其实具体的实现方式主要是对于插入排序的优化,在进行最后的插入操作中,让整个数组的值趋于有序的状态;

1. 希尔排序是对直接插入排序的优化。


2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。


3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定



4.希尔排序是不稳定的排序

运行结果:

 

🚀2.2堆排序

代码如下:

小根堆

class Solution { public int[] sortArray(int[] nums) { //堆排序 PriorityQueue<Integer> queue = new PriorityQueue<>(); for(int i = 0; i < nums.length;i ++){ queue.offer(nums[i]); } for(int i = 0;i < nums.length; i++){ nums[i] = queue.poll(); } return nums; } }

 大根堆

class Solution { public int[] sortArray(int[] nums) { //堆排序 PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1); for(int i = 0; i < nums.length;i ++){ queue.offer(nums[i]); } for(int i = nums.length-1;i >= 0; i--){ nums[i] = queue.poll(); } return nums; } }
大体思路:就是利用优先级队列的特性;

1. 堆排序使用堆来选数,效率就高了很多。

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

运行结果:

 

🚀2.3分治排序

 代码如下:

class Solution { public int[] sortArray(int[] nums) { //分治 sort(nums,0,nums.length-1); return nums; } //分治操作 public void sort(int[] nums,int l,int r){ //边界判断 if(l >= r){ return; } //找到我们对应的mid; int mid = nums[new Random().nextInt(r - l + 1) + l]; //进行核心分治 int left = l - 1; int right = r + 1; int i = l; while(i < right){ if(nums[i] < mid){ left ++; swap(nums,left,i); i++; }else if(nums[i] == mid){ i++; }else{ right --; swap(nums,right,i); } } //[l left][left + 1 right - 1][right r] sort(nums,l,left); sort(nums,right,r); } public void swap(int[] nums,int left,int right){ int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; } }
大体思路:其实就是分为三块,然后对于左右两块进行递归分治操作

1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序


2. 时间复杂度:O(N*logN)


3. 空间复杂度:O(logN)


4. 稳定性:不稳定

运行结果:

🚀 2.4归并排序

代码如下:

class Solution { public int[] sortArray(int[] nums) { //归并排序 sort(nums, 0, nums.length - 1); return nums; } public void sort(int[] nums, int left, int right) { //边界判断 if (left >= right) { return; } //获取中间值 int mid = (left + right) / 2; //分治 sort(nums, left, mid); sort(nums, mid + 1, right); //合并 int[] temp = new int[right - left + 1]; int cur1 = left; int cur2 = mid + 1; int i = 0; while (cur1 <= mid && cur2 <= right) { if (nums[cur1] <= nums[cur2]) { temp[i] = nums[cur1]; i++; cur1++; } else { temp[i] = nums[cur2]; i++; cur2++; } } while (cur1 <= mid) { temp[i] = nums[cur1]; i++; cur1++; } while (cur2 <= right) { temp[i] = nums[cur2]; cur2++; i++; } //放到我们的nums数组中 for (int j = left; j <= right; j++) { nums[j] = temp[j - left]; } } }
大体思路:就是不断分为一个一个元素,然后再两两合并即可~~

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定

 运行结果:

📚️3.总结

小小透露一下,某阿里**的笔试题中考到过算法的稳定性哦:

冒泡:稳定     插入:稳定    归并:稳定

选择:不稳定    希尔:不稳定    堆排:不稳定    分治:不稳定

本期主要讲解了关于排序算法的7种解题方式,涉及冒泡,选择,插入,希尔,堆排,分治,并归排序~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

😊😊  期待你的关注~~~

Read more

WebSocket 超细致完整用法讲解(含原理 + 前端 + 后端 + 实战案例 + 避坑)

你想要透彻掌握 WebSocket 的完整用法,我会从核心原理、前后端完整代码、使用场景、核心 API、心跳保活、常见问题等维度,一步步细致讲解,内容通俗易懂,学完就能直接落地开发。 一、WebSocket 核心认知(必懂,理解了用法才通透) 1. WebSocket 是什么? WebSocket 是 HTML5 新增的一种「全双工、持久化」的网络通信协议,协议标识是 ws://(明文)和 wss://(加密,推荐生产环境用),是 HTTP 协议的补充和升级。 2. 为什么需要 WebSocket?HTTP 协议的痛点 HTTP 协议是 「单工 / 半双工」、「短连接」、「无状态」 的通信模式,

By Ne0inhk
自动化打造信息影响力:用 Web Unlocker 和 n8n 打造你的自动化资讯系统

自动化打造信息影响力:用 Web Unlocker 和 n8n 打造你的自动化资讯系统

一、研究背景 在信息爆炸的时代,及时获取高质量行业资讯成为内容创作者、运营者以及研究者的刚需。无论是IT、AI领域的技术动态,还是招聘、人才市场的趋势新闻,第一时间掌握热点、总结观点并进行内容输出,正逐渐成为提升影响力与构建个人/组织品牌的关键手段。 为实现“日更内容”目标,很多人开始探索自动化的路径——使用爬虫工具定期抓取目标网站内容,借助 AI 模型自动生成摘要,再将结果推送至社群平台。这一流程的核心,是稳定、高效地获取网页数据,在实际操作中,却出现了很多问题: * 首先是出现了验证码,阻断自动化流程; * 紧接着是请求返回403 Forbidden,提示IP被封; * 最终是目标网站直接对我们常用IP段进行了临时封禁,哪怕切换机器或重启网络都无济于事。 按照检查方法,当处于非爬虫操作时,我们在F12控制台输入window.navigator.webdriver时,显示的是false,输入进去出现了刺眼的红色报错,而且显示也出现了True, “Failed to load resource: the server responded with

By Ne0inhk

Llama3-8B对话体验差?open-webui界面调优实战案例

Llama3-8B对话体验差?open-webui界面调优实战案例 1. 为什么Llama3-8B在open-webui里“不好用” 你是不是也遇到过这种情况:明明拉下了Meta-Llama-3-8B-Instruct的GPTQ-INT4镜像,显卡是RTX 3060,vllm也跑起来了,open-webui网页也打开了,可一输入问题,响应慢、回复短、上下文断连、甚至反复重复同一句话?不是模型不行,而是默认配置没对上——就像给跑车装了自行车刹车片。 Llama3-8B本身素质过硬:80亿参数、原生8k上下文、英语指令遵循能力对标GPT-3.5、MMLU 68+、HumanEval 45+,单卡3060就能跑。但它对对话系统层的调度逻辑非常敏感。open-webui作为前端界面,默认采用的是通用型API调用策略,而没针对Llama3系列的tokenizer行为、stop token设计、streaming节奏做适配。结果就是: * 模型已生成完,界面还在等“结束信号”; * 多轮对话中,system prompt被意外截断或覆盖; * 中文输入时,因token边界识别不准,

By Ne0inhk
【Linux网络系列】:JSON+HTTP,用C++手搓一个web计算器服务器!

【Linux网络系列】:JSON+HTTP,用C++手搓一个web计算器服务器!

🔥 本文专栏:Linux网络Linux实践系列 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录:别害怕选错,人生最遗憾的从不是‘选错了’,而是‘我本可以’。每一次推倒重来的勇气,都是在给灵魂贴上更坚韧的勋章。 ★★★ 本文前置知识: 序列化与反序列化 引入 在之前的博客中,我详细介绍了序列化 与反序列化 的概念。对于使用 TCP 协议进行通信的双方,由于 TCP 是面向字节流的,在发送数据之前,我们通常需要定义一种结构化的数据来描述传输内容,并以此作为数据的容器。在 C++ 中,这种结构化数据通常表现为对象或结构体。然而,我们不能直接将结构体内存中对应的字节原样发送到另一端,因为直接传递内存字节会引发字节序 和结构体内存对齐 的问题。不同平台、不同编译器所遵循的内存对齐规则可能不同,这可能导致接收方在解析结构体字段时出现错误。 因此,我们需要借助序列化 。序列化 是指将结构化的数据按照预定的规则转换为连续的字节流。其主要目的是屏蔽平台差异,使得位于不同平台的进程能够以统一的方式解析该字节流。序列化通常分为两种形式:文本序列化 与二进制序列化 。 文

By Ne0inhk