啦啦啦又来了~今天写的是分治算法中的Kth Largest Element in an Array,题目如下:
215 | Kth Largest Element in an Array | 38.1% | Medium |
题目的描述是这样的:
For example,
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
好吧我们讲中文,就是给一个无序数组,要求找出第k大的值。既然是放在分治算法的题,想想就知道...肯定有时间复杂度的限制的(虽然题目没说orz...
当然,如果我们把数组先排个序然后去找第k大的数,那样肯定是可以的啦,而且最快的排序算法的时间复杂度也才O(nlog n),就算你最后再去把整个数组遍历一遍(虽然没这个必要),最终的时间复杂度肯定也不会大过O(nlog n)的,但是我还是偏要用一下分治算法这个思想orz学以致用嘛
int findKthLargest(vector<int>& nums, int k)
{
int size=nums.size();
int v=nums[0];
vector<int> small;
vector<int> equal;
vector<int> large;
for(int i=0;i<size;i++)
{
if(nums[i]<v)
{
small.push_back(nums[i]);
}
else if(nums[i]==v)
{
equal.push_back(nums[i]);
}
else if(nums[i]>v)
{
large.push_back(nums[i]);
}
}
if(k<=large.size())
{
return findKthLargest(large,k);
}
else if(k>=large.size()&&k<=(large.size()+equal.size()))
{
return v;
}
else
{
return findKthLargest(small,k-large.size()-equal.size());
}
}
算法的思想呢,就是先随机选取一个数v,将数组分成三部分:比v小的、等于v的还有比v大的;接下来,如果比v大的数不足k,那么就利用递归在等于v的数中找第k-m大的值(假设m为比v大的数的个数),如果还是不行,那就只能在比v小的数中找第k-m-n大的数了(假设n为等于v的数的个数)。就这样我们把在一个比较大的数组寻找转化成了在小一点的数组中进行寻找。这个算法在我看来,就是牺牲了空间复杂度去换取时间复杂度。如果v选的不好,很容易造成空间不足的情况。一开始我直接把第一个数作为v,结果在测试时就遇到了很尴尬的情况...
Status:
Memory Limit Exceeded
至于出现的原因...呵呵,可耻的测试程序给了一个十分可耻的input:4999,4998,4997,... ,1,0(手动微笑
这样的input配上我那个算法...空间不会溢出才怪...
所以嘛...这个算法的精髓就是...v是随机取的...所以就变成了这样
int findKthLargest(vector<int>& nums, int k)
{
int size=nums.size();
int v=nums[size/2]; //就是这里改了
vector<int> small;
vector<int> equal;
vector<int> large;
for(int i=0;i<size;i++)
{
if(nums[i]<v)
{
small.push_back(nums[i]);
}
else if(nums[i]==v)
{
equal.push_back(nums[i]);
}
else if(nums[i]>v)
{
large.push_back(nums[i]);
}
}
if(k<=large.size())
{
return findKthLargest(large,k);
}
else if(k>=large.size()&&k<=(large.size()+equal.size()))
{
return v;
}
else
{
return findKthLargest(small,k-large.size()-equal.size());
}
}
这样就可以了...只要人品不会差到每次取到的位于n/2的数都是很极端的数(特别大或者特别小...)的话,就不会有什么大问题了orz