面试中LeetCode常见算法整理——排序

面试中LeetCode常见算法整理——排序

快速排序

用于求解 Kth Element 问题,使用快速排序的 partition() 进行实现。需要先打乱数组,否则最坏情况下时间复杂度为 O(N2)。

堆排序

用于求解 TopK Elements 问题,通过维护一个大小为 K 的堆,堆中的元素就是 TopK Elements。
堆排序也可以用于求解 Kth Element 问题,堆顶元素就是 Kth Element。
快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth
Element 的元素都是 TopK Elements。
可以看到,快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题。

1. Kth Element

215. Kth Largest Element in an Array

思路一:排序

时间复杂度 O(NlogN),空间复杂度 O(1)。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        assert(k>=1&&k<=nums.size());
        sort(nums.begin(), nums.end());
        return nums[nums.size()-k];
    }
};

思路二:优先队列

时间复杂度 O(NlogK),空间复杂度 O(K)。

class Solution {
public:
	int findKthLargest(vector<int>& nums, int k) {
		priority_queue<int, vector<int>, greater<int>> pq;
		for (int i = 0; i < nums.size(); ++i)
		{
			pq.push(nums[i]);
			if (pq.size() > k) //维护优先队列大小为k,保证队列中第k个元素最小
				pq.pop();
		}
		return pq.top();
	}
};

思路三:快速排序思想

时间复杂度 O(N),空间复杂度 O(1)

class Solution1 {
public:
	int findKthLargest(vector<int>& nums, int k) {
		assert(k >= 1 && nums.size() >= k);
		srand(time(NULL));
		return findKthLargest(nums, 0, nums.size() - 1, k - 1);
	}

private:
	int findKthLargest(vector<int>& nums, int l, int r, int k)
	{
		if (l == r)
			return nums[l];
		int p = partition(nums, l, r);
		if (p == k)
			return nums[p];
		else if (p < k)
			return findKthLargest(nums, p + 1, r, k);
		else
			return findKthLargest(nums, l, p - 1, k);
	}

	//从大到小排序
	int partition(vector<int>& nums, int l, int r)
	{
		swap(nums[l], nums[rand() % (r - l + 1) + l]);
		int v = nums[l];
		//[l+1, gt]>v, (gt,i)<=v
		int gt = l;
		int i = l + 1;
		while (i <= r)
		{
			if (nums[i] > v)
				swap(nums[i], nums[++gt]);
			++i;
		}
		swap(nums[l], nums[gt]);
		return gt;
	}
};

 2. 出现频率最多的 k 个数

347. Top K Frequent Elements

class Solution {
public:
	vector<int> topKFrequent(vector<int>& nums, int k) {
		unordered_map<int, int> m; //存储<值,频率>对儿
		for (auto num : nums)
			++m[num];
		assert(m.size() >= k); //保证有至少k个不同的元素
		//优先队列中存储的<频率,值>对儿
		priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
		for (auto it = m.begin(); it != m.end(); ++it)
		{
			pq.push(make_pair(it->second, it->first));
			if (pq.size() > k) //注意此处条件的使用,可以避免元素比较;如果是==的话,还需多一次比较操作
				pq.pop();
		}
		vector<int> res;
		while (!pq.empty())
		{
			res.push_back(pq.top().second);
			pq.pop();
		}
		return res;
	}
};

3. 按照字符串出现次数对字符串排序

451. Sort Characters By Frequency

class Solution {
public:
    string frequencySort(string s) {
        if(s=="")
            return s;
        unordered_map<char, int> record;
        for(int i = 0;i<s.length();++i)
            record[s[i]]++;
        vector<pair<char, int>>vRecord(record.begin(), record.end());
        sort(vRecord.begin(), vRecord.end(), pair_cmp);
        string res = "";
        for(int i = 0;i<vRecord.size();++i)
            res+=string(vRecord[i].second, vRecord[i].first);
        return res;
    }
private:
    static bool pair_cmp(const pair<char, int> &lhs,const pair<char, int> &rhs)
    {
        return lhs.second>rhs.second;
    }
};

4. 荷兰国旗问题

75. Sort Colors

本质是三路快速排序思想。

class Solution {
public:
    void sortColors(vector<int>& nums) {
        //[0, zero] == 0
        int zero = -1;
        //[two, n-1] == 2;
        int n = nums.size();
        int two = n;
        int i = 0;
        while(i<two)
        {
            if(nums[i] == 0)
                swap(nums[i++], nums[++zero]);
            else if(nums[i] == 1)
                ++i;
            else
                swap(nums[i], nums[--two]);
        }
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值