• 力扣-排序算法


    排序算法,一般都可以使用std::sort()来快速排序。

    这里介绍一些相关的算法,巩固记忆。

    快速排序

    二分查找有一丢丢像。

    首先选择一个基准元素,一般就直接选择第一个。然后两个指针,一个指向第一个,一个指向最后一个。第一个现在是空,就从最后一个开始,跟基准元素做判断,小于基准元素的就放到第一个位置,然后第一指针往后移。按这种顺序直到两个指针相遇,相遇的位置放入基准元素。然后从基准元素劈开两半,再按相同方法排序。

    1. void quicksort(vector<int> nums,int l,int r){
    2. if(l+1>=r)
    3. return;
    4. int first=l,last=r-1;
    5. int key=nums[first];
    6. while(first<=last){
    7. while(first=key)
    8. last--;
    9. nums[first]=nums[last];
    10. while(first
    11. first++;
    12. nums[last]=nums[first];
    13. }
    14. nums[first]=key;
    15. quicksort(nums,l,first);
    16. quicksort(nums,first+1,r);
    17. }

    归并算法

    归并算法是一种分治算法,先分再治。比如说8个数字。先分成4个4个,然后4个内部再继续分,分成2个2个。2个排好序后合并,4个排好序后再合并。

    1. void merge_sort(vector<int> &nums,int l,int r,vector<int>& temp){
    2. if(l+1>=r)
    3. return ;
    4. int m=(l+r)/2;
    5. merge_sort(nums,l,m,temp);
    6. merge_sort(nums,m+1,r,temp);
    7. int a=l,b=m,i=l;
    8. while(a
    9. if(nums[a]
    10. nums[i++]=nums[a++];
    11. else
    12. nums[i++]=nums[b++];
    13. }
    14. for(i=l;i
    15. nums[i]=temp[i];
    16. }

    插入排序

    首先是一个数,本来就有序。接着两个数进行排序。接着三个数。

    所谓插入,比如说八个数进行排序,其实前七个已经有序,这个时候只需要把第八个插入到前七个数的合适位置即可。怎么插入,就从后往前,一个一个比较,如果小于就往前移。

    1. void insert_sort(vector<int>& nums,int n){
    2. int i,j;
    3. for(i=0;i
    4. for(j=i;j>0;j--){
    5. if(nums[j]>nums[j-1])
    6. swap(nums[j],nums[j-1]);
    7. }
    8. }
    9. }

    冒泡排序

    相邻两个数比较,大的往后移,每一轮最大的数将会移到最后。

    可以进行一个优化,可能出现一种情况,从第二轮过后,其实数组已经是有序的了,但是按照算法步骤来走的话,即使已经排好序了,但仍是会进行后边的比较,知道全部比较完成

    因此,我们可以对代码进行优化,如果发现在某趟排序中,没有发生一次交换, 可以提前结束冒泡排序

    解决方式:可以通过一个标志位来进行判断

    1. void bubble_sort(vector<int>& nums,int n){
    2. int flag=false;
    3. int i,j;
    4. for(i=1;i
    5. flag=false;
    6. for(j=1;j1;j++){
    7. if(nums[j]-1]){
    8. swap(nums[j],nums[j-1]);
    9. flag=true;
    10. }
    11. }
    12. if(flag==false)
    13. return ;
    14. }
    15. }

    选择排序

    选择最小的数跟第一个数交换,按照同样的方法对后面的n-1个进行排序。

    1. void select_sort(vector<int>& nums,int n){
    2. int i,j;
    3. for(i=0;i
    4. int m=i;
    5. for(j=i+1;j
    6. if(nums[j]
    7. m=j;
    8. }
    9. }
    10. swap(nums[i],nums[m]);
    11. }
    12. }

    215.数组中的第K个元素

    215. 数组中的第K个最大元素

    给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

    请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

    示例 1:

    输入: [3,2,1,5,6,4], k = 2输出: 5
    

    示例 2:

    输入: [3,2,3,1,2,4,5,5,6], k = 4输出: 4

    提示:

    • 1 <= k <= nums.length <= 10^{5}
    • -10^{4} <= nums[i] <= 10^{4}

    题解

    可以利用快速排序的思想来解决这个问题。

    选择一个数,然后将大于它的数字往后移,小于的往前移。如果这个刚好是第k位,直接返回。如果不是,大于k,则对前面做相同的排序,如果不是就对后面做相似的排序。这里的k指的是第k大,因此从小到大排就是第n-k位。

    1. class Solution {
    2. public:
    3. int quickselect(vector<int> &nums,int l,int r,int k){
    4. if(l==r)
    5. return nums[k];
    6. int p=nums[l],i=l-1,j=r+1;
    7. while(i
    8. do i++; while (nums[i] < p);
    9. do j--; while (nums[j] > p);
    10. if(i
    11. swap(nums[i],nums[j]);
    12. }
    13. if(k<=j)
    14. return quickselect(nums,l,j,k);
    15. else
    16. return quickselect(nums,j+1,r,k);
    17. }
    18. int findKthLargest(vector<int> &nums, int k) {
    19. int n=nums.size();
    20. return quickselect(nums,0,n-1,n-k);
    21. }
    22. };

    347.前k个高频元素

    347. 前 K 个高频元素

    题目

    给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

    示例 1:

    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]
    

    示例 2:

    输入: nums = [1], k = 1
    输出: [1]

    提示:

    • 1 <= nums.length <= 10^{5}
    • k 的取值范围是 [1, 数组中不相同的元素的个数]
    • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

    题解

    可以使用桶排序,使用STL库中的unordered_map,提供了一种基于哈希表的键值对容器。

    可以对每一个数字出现的次数进行计算并且存储。

    1. unordered_map<int,int> m;
    2. for(int num:nums) m[num]++;

    接着进行排序,然后再定义一个新的数组用来存储要返回的数组。

    1. class Solution {
    2. public:
    3. vector<int> topKFrequent(vector<int>& nums, int k) {
    4. unordered_map<int,int> m;
    5. for(int num:nums) m[num]++;
    6. vectorint,int>> s;
    7. for(auto t:m)
    8. s.push_back({t.second,t.first});
    9. sort(s.begin(),s.end());
    10. vector<int> ans;
    11. int t=s.size()-1;
    12. while(k--){
    13. ans.push_back(s[t--].second);
    14. }
    15. return ans;
    16. }
    17. };

    排序这里也有一个库可以使用。

     是标准模板库(STL)的一部分,用于实现优先队列。

    优先队列是一种特殊的队列,它允许我们快速访问队列中具有最高(或最低)优先级的元素。

    1. class Solution {
    2. public:
    3. vector<int> topKFrequent(vector<int>& nums, int k) {
    4. unordered_map<int,int> m;
    5. for(int num:nums) m[num]++;
    6. priority_queueint,int>> s;
    7. for(auto i:m) s.emplace(i.second,i.first);
    8. vector<int> ans;
    9. while(k--){
    10. ans.push_back(s.top().second);
    11. s.pop();
    12. }
    13. return ans;
    14. }
    15. };

    不得不说如果熟悉使用STL库,真的省事很多。

  • 相关阅读:
    70B大模型训练秘方① :数据集创建与评估
    Linux安装Mariadb数据库
    JDK17 New Feature
    MySQL忘记密码后重置密码(windows版本)
    基于社交网络优化的BP神经网络(分类应用) - 附代码
    中国炭黑增强轮胎行业盈利动态与供需趋势预测报告2022-2028年
    Linux系统编程基础:进程控制
    Ubuntu系统之管理文件权限一
    android 布局 横屏 android横屏适配
    unresolved external symbol w32_fcntl
  • 原文地址:https://blog.csdn.net/weixin_63551790/article/details/140298651