1. 程式人生 > >【C++實現】第k大元素 時間複雜度為O(n),空間複雜度為O(1)

【C++實現】第k大元素 時間複雜度為O(n),空間複雜度為O(1)

解題思路:

二基準快速排序,在排序時判斷每次找到的標記點下標 p 與 n-k 的大小,若小於n-k,則只需在p的右側繼續遞迴,若大於 p 則只需在p 的左側遞迴,直至 p 與 n-k 相等

vs可執行程式碼

#include<ctime>
#include<vector>
#include<iostream>
#include<cassert>
#include<string>
using namespace std;
namespace SortTestHelper {

	// 生成有n個元素的隨機陣列,每個元素的隨機範圍為[rangeL, rangeR]
	vector<int> generateRandomArray(int n, int rangeL, int rangeR)
	{
		assert(rangeL <= rangeR);

		vector<int> v;
		srand(time(NULL));
		for (int i = 0; i < n; i++)
			v.push_back( rand() % (rangeR - rangeL) + rangeL);
		return v;
	}
}

class Solution {
public:
	/*
	* @param n: An integer
	* @param nums: An array
	* @return: the Kth largest element
	*/
	
	int __partition(vector<int> &arr, int l, int r)
	{
		swap(arr[l], arr[rand() % (r - l) + l]);
		int e = arr[l];
		int i = l + 1, j = r - 1;
		while (true)
		{
			while (i < r && arr[i] < e) i++;
			while (j > l && arr[j] > e) j--;
			if (i>j) break;
			swap(arr[i], arr[j]);
			i++;
			j--;
		}
		swap(arr[l], arr[j]);
		return j;
	}
	void __quickSort(vector<int> &arr, int l, int r)
	{
		if (r - l < 2) return;
		int p = __partition(arr, l, r);
		__quickSort(arr, p + 1, r);
		__quickSort(arr, l, p);
	}
	void quickSort(vector<int> &arr, int n)//全部排序
	{
		srand(time(NULL));
		__quickSort(arr, 0, n);
	}



	//只用於找到第k大的元素 只需下面三個函式與第一個函式即可
	void __quickSortPart(vector<int> &arr, int l, int r)
	{
		if (r - l < 2) return ;
		int p = __partition(arr, l, r);
		if (p < index)
			__quickSortPart(arr, p + 1, r);
		else if (p>index)
			__quickSortPart(arr, l, p);
		else return ;
	}
	void quickSortPart(vector<int> &arr, int n)
	{
		srand(time(NULL));
		__quickSortPart(arr, 0, n);
	}
	
	int kthLargestElement(int n, vector<int> &nums)
	{
		// write your code here

		int len = nums.size();
		index = len - n;
		quickSortPart(nums, len);
		cout << nums[index] << endl;
		return nums[index];
	}

	//判斷排序成功與否
	bool isSorted(const string &sortName, vector<int>& arr, int n)
	{
		for (int i = 0; i < n - 1; i++)
		if (arr[i] > arr[i + 1])
		{
			cout << sortName << "無序!" << endl;
			return false;
		}
		cout << sortName << "有序!" << endl;
		return true;
	}
	//測試排序時間
	void testSort(const string &sortName, vector<int>& arr,int n)
	{
		clock_t startTime = clock();
		quickSort(arr, n);
		clock_t endTime = clock();

		assert(isSorted(sortName, arr, n));
		cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;

		return;
	}

private:
	int index;
};

int main()
{
	int n = 1000000;
	vector<int> &v = SortTestHelper::generateRandomArray(n, 0, n);
	Solution s;
	s.kthLargestElement(999,v);//找到第999大的數
	s.testSort("Quick Sort",v,n);

	cout << v[n - 999];//輸出排序之後的第999大的數

	cout << endl;
	system("pause");
	return 0;
}

提交程式碼  此程式碼可50ms內AC 

class Solution {
public:
	/*
	* @param n: An integer
	* @param nums: An array
	* @return: the Kth largest element
	*/
	
	int __partition(vector<int> &arr, int l, int r)
	{
		swap(arr[l], arr[rand() % (r - l) + l]);
		int e = arr[l];
		int i = l + 1, j = r - 1;
		while (true)
		{
			while (i < r && arr[i] < e) i++;
			while (j > l && arr[j] > e) j--;
			if (i>j) break;
			swap(arr[i], arr[j]);
			i++;
			j--;
		}
		swap(arr[l], arr[j]);
		return j;
	}
	
	void __quickSortPart(vector<int> &arr, int l, int r)
	{
		if (r - l < 2) return ;
		int p = __partition(arr, l, r);
		if (p < index)
			__quickSortPart(arr, p + 1, r);
		else if (p>index)
			__quickSortPart(arr, l, p);
		else return ;
	}
	void quickSortPart(vector<int> &arr, int n)
	{
		srand(time(NULL));
		__quickSortPart(arr, 0, n);
	}
	
	int kthLargestElement(int n, vector<int> &nums)
	{
		// write your code here

		int len = nums.size();
		index = len - n;
		quickSortPart(nums, len);
		return nums[index];
	}

private:
	int index;
};