剑指offer--快速排序变形(5、29)

offer5

题目:输入n个整数,输出其中最小的k个。

例如输入123456788个数字,则最小的4个数字为1234


题目可以利用快速排序第一步来做,先选取首位的值,将小于该值的放在左边,大于等于该值的放在右边,如果该值的位置正好是k,那么该值连同左边的值就是最小的k个,如果位置小于k,那么在右边继续执行,如果大于k,那么在左边继续执行,时间复杂度平均是O(N)。

代码:


int FindPos(int *a, int low, int high)
{
	int k=a[low];
	int i,j;
	i=low;
	j=high;

	while (i<j)
	{
		while (j>i && a[j]>=k)
			j--;
		a[i]=a[j];
		while (i<j && a[i]<k)
			i++;
		a[j]=a[i];
	}
	a[i]=k;
	return i;
}

void Find(int *a, int low, int high, int key)
{
	if (low<=high)
	{
		int pos=FindPos(a, low, high);
		if (pos+1==key)
		{
			int i=0;
			while (i<=pos)
			{
				printf("%3d ",a[i]);
				i++;
			}
			printf("\n");
		}
		if (pos+1<key)
			Find(a, pos+1, high, key);
		if (pos+1>key)
			Find(a, low, pos-1, key);
	}
	
}


还有另外一种思路,类似动态规划

首先我从头开始拿出k个值来,保存好,然后从数组读入一个新的值,如果新值比 k个值中最大值要小,那么就替换掉最大值,否则不替换,直到数组中所有数据全部读取完。k比较小时可以采用数组,k比较大值采用最大堆存储,首位就是k中的最大值,更新最大值也很方便,复杂度是O(logk)。


offer29

输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)

左右开始,然后找到左边第一个偶数和右边第一个奇数,直到左右相遇。奇偶判断可以采用位运算,最位为1那么就是奇数,否则为偶数。

代码:

void Reorder(int *a, int low, int high)
{
	if (!a || low>=high || low<0 || high<0)
		return;

	while (low<high)
	{
		while (low<high && a[low]%2)
			low++;
		while (low<high && a[high]%2==0)
			high--;
		if (low<high)
		{
			swap(a[low], a[high]);
			low++;
			high--;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值