牛客网《剑指Offer》编程 29.最小的k个数 (解法1,需要改变原数组)

题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

解题思路

由于快速排序每次能够把一个数放置在正确的位置上。因此,我们可以使用快速排序的Partition函数,对数组进行排序,直到第k个数被放在数组中第k个位置上为止。此时第k个数的左边都是比它小的数,右边都是比它大的数。最后输出前k个数就可以了。

使用快速排序中的Partition函数。Partition函数排列数组下标取值在[low,high]的顺序,能够将数组按照pivot值分为左右两个部分,左边的部分比pivot小,右边的比它大。该函数返回pivot值的坐标idx。如果idx比k-1大,说明前k个数在idx的左边,因此排列坐标取值范围为[low,idx-1]的数;如果idx比k-1小,说明前k个数有一部分已经在pivot左边了,还有一部分在右侧,因此排列pivot右侧的数。下标取值范围为[idx+1,high]。

一直排列数组知道数组第k个数被放在数组中应该放置的位置上。此时前k个数就是整个数组中最小的k个数。

但是该算法改变了原数组。因此在OJ上并没有通过。

代码实现

#include <vector>
#include <string>
#include <iostream>
using namespace std;
int Partition(vector<int> &input, int low, int high) {
	int pivot = input[low];
	while (low < high) {
		while (low < high&&input[high] >= pivot) {
			high--;
		}
		swap(input[low], input[high]);
		while (low < high&&input[low] <= pivot) {
			low++;
		}
		swap(input[low], input[high]);
	}
	return low;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
	int low = 0;
	int high = input.size() - 1;
	vector<int> res;
	int idx = Partition(input, low, high);
	while (idx != k - 1) {
		if (idx > k - 1) {
			high = idx - 1;
			idx = Partition(input, low, high);
		}
		else if (idx < k - 1) {
			low = idx + 1;
			idx = Partition(input, low, high);
		}
	}
	for (int i = 0; i <= idx; i++) {
		res.push_back(input[i]);
	}

	return res;
}

猜你喜欢

转载自blog.csdn.net/eriHanami/article/details/82945873