第k大元素
题目
在数组中找到第k大的元素
注意事项
你可以交换数组中的元素的位置样例
给出数组 [9,3,2,4,8],第三大的元素是 4
给出数组 [1,2,3,4,5],第一大的元素是 5,第二大的元素是 4,第三大的元素是 3,以此类推挑战
要求时间复杂度为O(n),空间复杂度为O(1)
题解
1.快排法O(nlogn)
具体参看中位数
public class Solution {
/**
* @param nums: A list of integers.
* @return: An integer denotes the middle number of the array.
*/
public int median(int[] nums) {
return getMinK(nums,0,nums.length-1,(nums.length-1)/2);
}
private int getMinK(int[] nums, int left, int right, int k)
{
int i = left;
int j = right;
while (i != j)
{
while (nums[j] >= nums[left] && i < j)
{
j--;
}
while (nums[i] <= nums[left] && i < j)
{
i++;
}
swap(nums,i,j);
}
swap(nums,left,i);
if (i == k)
{
return nums[i];
}
else if (i < k)
{
return getMinK(nums,i+1,right,k);
}
else
{
return getMinK(nums,left,i-1,k);
}
}
private void swap(int[] nums, int i, int j)
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
2.BFPRT算法
BFPTR算法仅仅是改变了快速排序Partion中的pivot值的选取,每次选择五分中位数的中位数作为pivot,这样可以使划分比较合理,已达到O(n)的时间复杂度。算法步骤如下:
a.将数组以每组5个元素进行划分,且至多只有一个组由n%5个元素组成。
b.对每组进行插入排序,然后选出中位数并和数组的首位元素进行换位。
c.对于所有组中的中位数进行递归找到中位数的中位数。
d.以中位数的中位数为pivot进行快速排序查找。
维基链接
class Solution
{
/*
* @param k : description of k
*
* @param nums : array of nums
*
* @return: description of return
*/
public int kthLargestElement(int k, int[] nums)
{
return BFPTR(nums, 0, nums.length - 1, nums.length - k + 1);
}
void InsertSort(int a[], int l, int r)
{
for (int i = l + 1; i <= r; i++)
{
if (a[i - 1] > a[i])
{
int t = a[i];
int j = i;
while (j > l && a[j - 1] > t)
{
a[j] = a[j - 1];
j--;
}
a[j] = t;
}
}
}
int FindMid(int a[], int l, int r)
{
if (l == r)
{
return l;
}
int i = l;
int n = 0;
for (; i < r - 5; i += 5)
{
InsertSort(a, i, i + 4);
n = i - l;
swap(a, l + n / 5, i + 2);
}
InsertSort(a, i, r);
swap(a, l + n / 5, (i + r + 1) / 2);
n /= 5;
return n == l ? 1 : FindMid(a, l, l + n);
}
int Partion(int a[], int l, int r, int p)
{
swap(a, p, l);
int i = l;
int j = r;
int pivot = a[l];
while (i < j)
{
while (a[j] >= pivot && i < j)
j--;
a[i] = a[j];
while (a[i] <= pivot && i < j)
i++;
a[j] = a[i];
}
a[i] = pivot;
return i;
}
int BFPTR(int a[], int l, int r, int k)
{
int p = FindMid(a, l, r);
int i = Partion(a, l, r, p);
int m = i - l + 1;
if (m == k)
{
return a[i];
}
else if (m > k)
{
return BFPTR(a, l, i - 1, k);
}
return BFPTR(a, i + 1, r, k - m);
}
private void swap(int[] nums, int i, int j)
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
};
Last Update 2016.9.20