C/C++十大排序算法


常见的排序算法

在C++中,可以通过std::sort()进行排序,熟悉排序算法主要锻炼自己编程能力,加深自己对算法的理解。

在这里插入图片描述
算法时间复杂度:

在这里插入图片描述

比较类排序

通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。

冒泡排序

快速排序

插入排序

希尔排序

选择排序

堆排序

二路归并排序

多路归并排序

非比较类排序

不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

计数排序

桶排序

基数排序

快速排序类型题

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

题目描述

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

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

输入输出样例

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

题解

快速选择一般用于求解 k-th Element 问题,可以在 O(n) 时间复杂度,O(1) 空间复杂度完成求解工作。快速选择的实现和快速排序相似,不过只需要找到第 k 大的枢(pivot)即可,不需要对其左右再进行排序。

代码

class Solution {
public:   
int findKthLargest(vector<int>& nums, int k) {
	int l = 0, r = nums.size() - 1, target = nums.size() - k;
	while (l < r) {
		int mid = quickSelection(nums, l, r);
		if (mid == target) {
			return nums[mid];
		}
		if (mid < target) {
			l = mid + 1;
		}
		else {
			r = mid - 1;
		}
	}
	return nums[l];
}
// 辅函数 - 快速选择
int quickSelection(vector<int>& nums, int l, int r) {
	int i = l + 1, j = r;
	while (true) {
		while (i < r && nums[i] <= nums[l]) {
			++i;
		}
		while (l < j && nums[j] >= nums[l]) {
			--j;
		}
		if (i >= j) {
			break;
		}
		swap(nums[i], nums[j]);
	}
	swap(nums[l], nums[j]);
	return j;
}
};

75.颜色分类(Medium)

题目描述

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

输入输出样例

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

题解

类似三路快排,进行划分

代码

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int low=0,high=nums.size()-1;
        if(low>=high) return;
        int i=low,j=low;
        int k=high;
        while(i<=k){
            if(nums[i]==0) swap(nums[i++],nums[j++]);
            else if(nums[i]==2) swap(nums[i],nums[k--]);
            else i++;
        }
    }
};

桶排序类型题

347.前K个高频元素

题目描述

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

输入输出样例

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

代码

class Solution {
public:
	vector<int> topKFrequent(vector<int>& nums, int k) {
		unordered_map<int, int> counts;
		int max_count = 0;
		for (const int& num : nums) {
			max_count = max(max_count, ++counts[num]);
		}
		vector<vector<int>> buckets(max_count + 1);
		for (const auto& p : counts) {
			buckets[p.second].push_back(p.first);
		}
		vector<int> ans;
		for (int i = max_count; i >= 0 && ans.size() < k; --i) {
			for (const int& num : buckets[i]) {
				ans.push_back(num);
				if (ans.size() == k) {
					break;
				}
			}
		}
		return ans;
	}
};

451.根据字符出现频率排序(Medium)

题目描述

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

输入输出样例

输入:
"tree"

输出:
"eert"

解释:
'e'出现两次,'r''t'都只出现一次。
因此'e'必须出现在'r''t'之前。此外,"eetr"也是一个有效的答案。

代码

class Solution {
public:
    string frequencySort(string s) {
        unordered_map<char,int> mp;
        int maxmp=0;
        for(auto& ch:s){
            maxmp=max(maxmp,++mp[ch]);
        }
        vector<string> buckets(maxmp+1);
        for(auto &[ch,num]:mp){
            buckets[num].push_back(ch);
        } 
        string ret;
        for(int i=maxmp;i>0;i--){
            string &bucket=buckets[i];
            for(auto &ch:bucket){
                for(int k=0;k<i;k++){
                    ret.push_back(ch);
                }
            }
        }
        return ret;
    }
};

本文排序算法主要参考一像素博客学习整理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值