leetcode-最小的k个数

leetcode-最小的k个数
题目链接:题目传送门
题目大意是给定一个数组,然后寻找数组中的前k小个元素。
乍一看,这个题目倒是很符合它的简单标签,直接对原数组进行冒泡排序操作,之后复制出前k个元素即可得到目标数组,但是这样做耗时过大,所以,我们来温习下快速排序的步骤

  1. 找到一个基准位置,通常取数组范围的首位
  2. 确定哨兵i和哨兵j,分别指向数组的两端
  3. 对于哨兵i,从左到右寻找,直到找到一个比基准数值大的数字
  4. 对于哨兵j,从右到左寻找,直到找到一个比基准数值小的数字
  5. 将两个哨兵找到的数值对调位置,继续寻找过程,直到两个哨兵找到的位置相重合,即i==j
  6. 将基准位置的数值和哨兵i的位置的元素调换位置
    实际开发中,可以先让哨兵j出发,如此操作可以保证,最后两个哨兵重合的位置的值是小于基准位置的,方便后面的交换。
    把上面的流程翻译成代码就是下面的样子
public int[] getLeastNumbers(int[] arr, int k) {
		int[] result = new int[k];
		quickSort(arr, 0, arr.length-1);
		for(int i = 0; i < k; i++) {
			result[i] = arr[i];
		}
		
		return result;
    }
	
	public void quickSort(int[] arr, int l, int r) {
		if(l >= r) {
			return ;
		}
		//针对哨兵,进行左右排序
		int i = l, j = r;
		while(i < j) {
			while((i < j)&&(arr[j] >= arr[l])) {
				j--;
			}
			while((i < j)&&(arr[i] <= arr[l])) {
				i++;
			}
			int t = arr[i];
			arr[i] = arr[j];
			arr[j] = t;
		}
		int t = arr[l];
		arr[l] = arr[i];
		arr[i] = t;
		
		quickSort(arr, l, i-1);
		quickSort(arr, i+1, r);
	}

实际上,对于这样的题目,可以这样想,在快速排序的过程中,当一个基准确定位置后,就可以得知,在最后的排序完成的数组中,基准位置还是这个位置,所以不必要排序整个数组,只需要进行一部分的排序就可以解决top K问题

public int[] quickSort(int[] arr, int l, int r, int k) {
		
		int i = l, j = r;
		while(i < j) {
			while((i < j)&&(arr[j] >= arr[l])) {
				j--;
			}
			while((i < j)&&(arr[i] <= arr[l])) {
				i++;
			}
			
			int t = arr[i];
			arr[i] = arr[j];
			arr[j] = t;
		}
		
		int t = arr[l];
		arr[l] = arr[i];
		arr[i] = t;
		//此时已经确定了arr[l]就是位于最终数组下标为i的位置
		if(i > k) {
			//最终的结果小数组位于i的左边
			return quickSort(arr, l, i-1, k);
		}
		if(i < k) {
			//最终的结果小数组位于i的右边
			return quickSort(arr, i+1, r, k);
		}
		return Arrays.copyOf(arr, k);
	}

以前怎么都学不会的,现在能看进去了,奇怪的人类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值