(算法)最⼩的k个数————<分治-快排>

1. 题⽬链接:剑指Offer40.最⼩的k个数

2. 题⽬描述:

3. 解法(快速选择算法):

算法思路:

在快排中,当我们把数组「分成三块」之后: [l, left] [left + 1, right - 1] [right, r] ,我们可以通过计算每⼀个区间内元素的「个数」,进⽽推断出最⼩的k个数在哪 些区间⾥⾯。

那么我们可以直接去「相应的区间」继续划分数组即可。  

C++算法代码: 

class Solution 
{
public:
    vector<int>answer;  //答案
    void qsort(vector<int>& stock,int l,int r,int cnt)
    {
        //边界情况
        if(l>=r)
        {
            return;
        }
        //随机关键字
        int key=stock[rand()%(r-l+1)+l];
        //三区域划分
        int left=l-1,right=r+1,i=l;
        while(i<right)
        {
            if(stock[i]<key)
            {
                swap(stock[i++],stock[++left]);
            }
            else if(stock[i]>key)
            {
                swap(stock[i],stock[--right]);
            }
            else
            {
                i++;
            }
        }
        //判断
        int a=left-l+1,b=right-left-1,c=r-right+1;
        //当a部分大于cnt时,因为a部分还未排序,所以不能找到最小的cnt个元素
        if(a>=cnt)
        {
            qsort(stock,l,left,cnt);
        }
        //当a+b部分大于cnt时,由于b部分的元素都是一样的,所以可以直接在前cnt位置取数据,不在乎顺序
        else if(a+b>=cnt)
        {
            return ;
        }
        //当a+b部分小于cnt时,说明还需要在后面找一些元素
        else
        {
            qsort(stock,right,r,cnt-a-b);
        }
    }
    vector<int> inventoryManagement(vector<int>& stock, int cnt) 
    {
        //随机数种子
        srand(time(NULL));
        qsort(stock,0,stock.size()-1,cnt);
        return {stock.begin(),stock.begin()+cnt};
    }
};

Java算法代码:

class Solution
{
	public int[] getLeastNumbers(int[] nums, int k)
	{
		qsort(nums, 0, nums.length - 1, k);
		int[] ret = new int[k];
		for (int i = 0; i < k; i++)
			ret[i] = nums[i];
		return ret;
	}
	public void qsort(int[] nums, int l, int r, int k)
	{
		if (l >= r) return;
		// 1. 随机选择⼀个基准元素 + 数组分三块 
		int key = nums[new Random().nextInt(r - l + 1) + l];
		int left = l - 1, right = r + 1, i = l;
		while (i < right)
		{
			if (nums[i] < key) swap(nums, ++left, i++);
			else if (nums[i] == key) i++;
			else swap(nums, --right, i);
		}
		// 2. 分类讨论 
		int a = left - l + 1, b = right - left - 1;
		if (a > k) qsort(nums, l, left, k);
		else if (a + b >= k) return;
		else qsort(nums, right, r, k - a - b);
	}
	public void swap(int[] nums, int i, int j)
	{
		int t = nums[i];
		nums[i] = nums[j];
		nums[j] = t;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

课堂随笔

感谢支持~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值