随机快排
不稳定:当选择的x越靠经两侧,时间复杂度为O(n^2),空间复杂度O(n)
当选择的x越靠近中间,时间复杂度为O(n*log n),空间复杂度为O(logn)
912. 排序数组 - 力扣(LeetCode)
int static small;//设置全局区的静态变量,来定义排序x的位置后,在快排时的左右边界。 int static big; class Solution { public: void partition(vector<int>& nums,int left,int right,int x) { small = left;//小于x的分界处 big = right;//大于x的分界处 int i = left; while(big>=i) { if (nums[i] < x) { swap(nums[i++], nums[small++]); } else if (nums[i] > x) { swap(nums[i], nums[big--]); } else { i++; } } } void quickSort(vector<int>& nums,int left,int right) { if (left>=right) { return; } std::random_device rd; // 获取随机种子 std::mt19937 gen(rd()); // 使用mt19937引擎 std::uniform_int_distribution<int> distribution(left,right); // 生成[min, max]范围内的随机整数 int randomNumber = distribution(gen); int x = nums[randomNumber]; partition(nums, left, right, x);//给x对应的值进行排序 int a = small;//这里保存了samll和big的值,是因为quickSort函数执行后,small和big的值会改变。 int b = big; quickSort(nums,left,a-1); quickSort(nums,b+1,right); } };
2.给定一个无需数组,求第k大的数,并且返回k的值
思路:使用按照随机快排的方式,先随机一个数组的下标x,对其进行排序,再根据small-1和big+1的位置,查找是否x已经在范围内,如果不在就在对应一侧进行相同操作即可。
时间复杂度O(N) 空间复杂度O(1)
int static small; int static big; class Solution { public: void partition(vector<int>& nums,int left,int right,int x) { small = left;//小于x的分界处 big = right;//大于x的分界处 int i = left; while(big>=i) { if (nums[i]<x) { swap(nums[small++],nums[i++]); } else if(nums[i]>x) { swap(nums[big--],nums[i]); } else { i++; } } } int quickSort(vector<int>&nums,int key) { int left = 0; int right = nums.size() - 1; for (int i=0;i<nums.size();i++) { std::random_device rd; // 获取随机种子 std::mt19937 gen(rd()); // 使用mt19937引擎 std::uniform_int_distribution<int> distribution(left, right); // 生成[min, max]范围内的随机整数 int randomNumber = distribution(gen); int x = nums[randomNumber]; partition(nums,left,right,x); if (small-1>key) { right = small - 1; } else if (big+1<key) { left = big + 1; } else { return nums[small]; } } } //给定无序数组,找到第k大的数并且返回 int randomselect(vector<int>& nums,int k) { //找第k大的数,其实就是第n-k个。 return quickSort(nums,nums.size()-k); } };