首页 > 编程语言 >【Leetcode刷题记录】各种排序算法

【Leetcode刷题记录】各种排序算法

时间:2023-09-05 16:11:59浏览次数:36  
标签:size index temp nums int 排序 Leetcode 刷题

前言:这篇文章总结一下学习的几种排序算法,假设要对一个 vector<int> 数组进行降序排序,数组中一共有 n 个数。

1、冒泡排序

思想:冒泡排序的思想就是一共进行 n - 1 次循环,每次循环把范围内最小的数冒到最后面。

因此用内为双循环,外循环为冒泡的次数,内循环为每次冒泡的范围,通过比较和交换操作将最小值移到后面。

 1 // 第一个循环表示一共要泡几次
 2 // 第二个循环是冒泡
 3 for (int i = 0; i < nums.size() - 1; ++i) {
 4     for (int j = 0; j < nums.size() -i; ++j) {
 5         if (nums[j] < nums[j + 1]) {
 6             int temp = nums[j];
 7             nums[j] = nums[j + 1];
 8             nums[j + 1] = temp;
 9         }
10     }
11 }

2、简单选择排序

思想:简单选择排序非常粗暴!原理就是一共进行 n - 1 次循环,每次循环在范围内找到最大的数,然后把它移到前面!

同样是内外双循环,外循环为选择排序的次数,内循环每次找到范围内最大值,然后交换到最前面。

 1 // 外循环为选择的次数
 2 // 内循环为具体的选择操作
 3 for(int i = 0; i < nums.size() - 1; ++i) {
 4     int max = i;
 5     for (int j = i + 1; j < nums.size(); ++j) {
 6         if (nums[j] > nums[i]) {
 7             max = j;
 8         }
 9     }
10     if (max != i) {
11         int temp = nums[i];
12         nums[i] = nums[max];
13         nums[max] = temp;
14     }
15 }

3、直接插入排序

思想:直接插入排序的原理是当循环到下标 i 时,范围 [0,i-1] 已经保证有序,然后判断 nums[i] 是否大于 nums[i-1],如果是,则往回找到第一个元素下标 j ,使得 nums[j] >= nums[i],然后把 [j+1,i-1] 范围内元素后移一位,nums[j+1] = nums[i]。

 1 // 直接插入排序(原型)
 2 for (int i = 1; i < nums.size(); ++i) {
 3     if (nums[i] > nums[i - 1]) {
 4         int temp = nums[i];
 5         int j;
 6         for (j = i - 1; j >= 0 && nums[j] < temp; --j) {
 7             nums[j + 1] = nums[j];
 8         }
 9         nums[j + 1] = temp;
10     }
11 }

4、希尔排序

 思想:希尔排序是直接插入排序的改进。其原理是先设置一个阈值宽度,在这个范围内进行直接插入排序,使数组处于大致有序的状态(大的数基本在前面,中间的数基本在中间,小的数基本在后面)。

然后不断缩小阈值宽度直到它等于 1,此方法可以减少移动次数,因此效率上要优于直接插入排序。

 1 // 希尔排序(改进)
 2 int index = nums.size();
 3 do {
 4     index = index / 3 + 1;
 5     for (int i = index; i < nums.size(); ++i) {
 6         if (nums[i] > nums[i - index]) {
 7             int temp = nums[i];
 8             int j;
 9             for (j = i - index; j >= 0 && nums[j] < temp; j -= index) {
10                 nums[j + index] = nums[j];
11             }
12             nums[j + index] = temp;
13         }
14     }
15 } while (index > 1);

5、堆排序

思想:堆排序是简单选择排序的改进,其原理是首先把数组构造成一个小顶堆,然后每次将第一个元素与范围内最后一个元素交换,并重新构造小顶堆...

注意事项:构造小顶堆时,break 的条件不能有 = 。

 1 // 将数组构造成小顶堆
 2 for (int i = nums.size()/2 - 1; i >= 0; --i) {
 3     heapadjust(nums,i,nums.size() - 1);
 4 }
 5 
 6 // 堆排序,每次把最小的数移到最后面,然后重新构造堆
 7 for (int i = nums.size() - 1; i > 0; --i) {
 8     swap(nums,0,i);
 9     heapadjust(nums,0,i-1);
10 }
11 
12 // 构造小顶堆算法
13 void heapadjust(std::vector<int>& nums, int i, int n) {
14     int temp = nums[i];
15     for (int j = i * 2 + 1; j <= n; j = j * 2 + 1) {
16         if (j <= n - 1 && nums[j] > nums[j + 1]) {
17             ++j;
18         }
19         // 这里不能大于等于
20         if (nums[j] > temp) {
21             break;
22         }
23         nums[i] = nums[j];
24         i = j;
25     }
26     nums[i] = temp;
27 }
28 
29 void swap(std::vector<int>& nums, int i, int j) {
30     int temp = nums[i];
31     nums[i] = nums[j];
32     nums[j] = temp;
33 }

6、归并排序

思想:归并排序用到了分治的思想。将待排序的数组分为两个子数组各自排序,子数组排好后合并到一起即可。注意划分字数组的时候的返回条件,当左端点大于等于右端点时,直接返回!

 1 // nums2是一个中间变量,nums划分为两个有序子数组后,并入到nums2里面,然后再赋值给nums
 2 std::vector<int> nums2 = nums;
 3 sort(nums,nums2,0,nums.size()-1);
 4 
 5 // 归并排序算法
 6 void sort(std::vector<int>& nums1, std::vector<int>& nums2, int l, int r) {
 7     if (l >= r) {
 8         return;
 9     }
10     int m = l + (r - l) / 2;
11     sort(nums1, nums2, l, m);
12     sort(nums1, nums2, m + 1, r);
13     int k = l, ptr1 = l, ptr2 = m + 1;
14     while (ptr1 <= m && ptr2 <= r) {
15         nums2[k++] = nums1[ptr1] > nums2[ptr2] ? nums1[ptr1++] : nums2[ptr2++]; 
16     }
17     while (ptr1 <= m) {
18         nums2[k++] = nums1[ptr1++];
19     }
20     while (ptr2 <= r) {
21         nums2[k++] = nums1[ptr2++];
22     }
23     for (int i = l; i <= r; ++i) {
24         nums1[i] = nums2[i];
25     }
26 }

7、快速排序

思想:快速排序的思想是先选取一个中间数,然后通过交换操作将数组分为两个部分,大于等于中间数的数都在中间数的左边,小于等于中间数的数都在中间数的右边。然后对这两个区域分别进行快速排序。

具体的,每次就选取区域内的第一个元素作为中间数!

 1 // 对数组作快速排序
 2 quicksort(nums,0,nums.size()-1);
 3 
 4 // 快速排序算法
 5 void quicksort(std::vector<int>& nums, int l, int r) {
 6     if (l >= r) {
 7         return;
 8     }
 9     int m = getmid(nums,l,r);
10     quicksort(nums,l,m-1);
11     quicksort(nums,m+1,r);
12 }
13 
14 // 将区域分为两部分,同时返回中间数下标
15 int getmid(std::vector<int>& nums, int l, int r) {
16     int index = nums[l];
17     while (l < r) {
18         while (l < r && nums[r] <= index) {
19             r--;
20         }
21         swap(nums,l,r);
22         while (l < r && nums[l] >= index) {
23             l++;
24         }
25         swap(nums,l,r);
26     }
27     return l;
28 }
29 
30 void swap(std::vector<int>& nums, int i, int j) {
31     int temp = nums[i];
32     nums[i] = nums[j];
33     nums[j] = temp;
34 }

标签:size,index,temp,nums,int,排序,Leetcode,刷题
From: https://www.cnblogs.com/Archigenius/p/17679917.html

相关文章

  • leetcode1161最大层内元素之和
    dfslassSolution{public:unordered_map<int,vector<int>>m;voiddfs(TreeNode*root,intdepth){if(!root)return;intres=0;depth++;dfs(root->left,depth);dfs(root->right,depth);......
  • LeetCode -- 394. 字符串解码(栈处理字符串问题)
     我们用栈同时维护当前字符串和倍数以及要加倍的字符串当遇到"["时,我们保存当前字符串,即将当前字符cres串入栈;当遇到"]"时,res=cres+倍数*应加倍的字符串classSolution:defdecodeString(self,s:str)->str:stack,res,multi=[],"",0......
  • 排序算法
    排序参考:视频交换排序:冒泡排序和快速排序冒泡:比较两个元素,比较大就往后放,那么每一次都会将一个最大的元素放在末尾,所以下一次就不需要遍历最后哪些排完序的元素。时间复杂度:O(n^2)稳定#include<vector>#include<iostream>usingnamespacestd;voidblue_blue(vector<in......
  • 【 LeetCode题解 】203. 移除链表元素
    【LeetCode题解】203.移除链表元素题目链接:https://leetcode.cn/problems/remove-linked-list-elements/博客主页链接:DuckBro博客主页关注博主,后期持续更新系列文章***感谢观看,希望对你有所帮助***目录【LeetCode题解】203.移除链表元素......
  • 排序算法知识点和常见面试题
    查找和排序算法知识点和常见面试题查找二分查找排序算法知识点冒泡排序插入排序选择排序快速排序二分思维+递归思维#include<stdio.h>intFindPos(int*a,intlow,inthigh);voidQuickSort(int*a,intlow,inthigh);intmain(void){ inta[6]={-2,1,......
  • 【刷题笔记】35. Search Insert Position
    题目Givenasortedarrayandatargetvalue,returntheindexifthetargetisfound.Ifnot,returntheindexwhereitwouldbeifitwereinsertedinorder.Youmayassumenoduplicatesinthearray.Example1:Input:[1,3,5,6],5Output:2Example2:I......
  • LeetCode 周赛上分之旅 #43 计算机科学本质上是数学吗?
    ⭐️本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]和BaguTreePro知识星球提问。学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场LeetCode周赛的解题报告,一......
  • 前端歌谣的刷题之路-第十一题-伪类选择器
     目录前言题目 核心代码总结前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷本题目源自于牛客网......
  • 前端歌谣的刷题之路-第十二题-伪元素
     目录前言题目核心代码总结前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷本题目源自于牛客网......
  • 力扣——1 [两数之和](https://leetcode.cn/problems/two-sum/)
    给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。示例1:输入:nums=[2,7,11,15],tar......