1. 程式人生 > >牛客網《劍指Offer》程式設計 29.最小的k個數 (解法1,需要改變原陣列)

牛客網《劍指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;
}