Kth Largest Element in an Array
2015-08-29 15:30
381 查看
该题最直观的解决思路是先对数组进行排序,然后返回第k个元素即可,但是该方法的时间复杂度为 O(nlog(n)), 较高。比较高校的思路有两种:一种是堆排序的思路,一种是快拍的思路。
一、堆排序的思路。该思路设置容量为 k 的小顶堆,将剩余的元素每一个和堆顶元素进行比较,若比堆顶元素小则该元素必然不会是第 k 大的元素,直接处理下一个元素;若比堆顶元素大则说明堆顶元素不可能是第 k 大的元素,替换堆顶元素与该元素,调整堆。 每调整一次堆的时间复杂性为 O(log(k)),总共有 n 个元素,则该思路的总时间复杂度为:O(n(log(k)))。
int findKthLargest(vector<int>& nums, int k){
int len = nums.size();
int i = (k - 1 - 1)/2;
int tmp;
//调整初始堆
while(i >= 0){
int tmpi = i;
tmp = nums[i];
int j = i*2 + 1;
while(j < k){
if(j+1 < k && nums[j+1] < nums[j])
j++;
if(nums[j] >= tmp)
break;
nums[i] = nums[j];
i = j;
j = i*2 + 1;
}
nums[i] = tmp;
i = tmpi - 1;
}
//遍历剩余元素
for(int l = k; l < len; l++){
if(nums[l] <= nums[0])
continue;
nums[0] = nums[l];
tmp = nums[0];
i = 0;
int j = i*2 + 1;
while(j < k){
if(j + 1 < k && nums[j + 1] < nums[j])
j++;
if(nums[j] >= tmp)
break;
nums[i] = nums[j];
i = j;
j = i*2 + 1;
}
nums[i] = tmp;
}
return nums[0];
}
二、快排的思路。该思路根据快速排序的思路进行处理,首先选择数组首元素 A 进一次快排处理,使得比它小的元素都在其前面比它大的元素都在其后面,处理之后若 A 此时的位置在第 k 个位置,则直接返回,否则若比 k 小,则对其之后的元素进行同样的处理,若比 k 大则对其之前的元素进行同样的处理。直到某一次处理的元素其位置就在第 k 个元素的位置返回即可。该思路最坏情况下需要对一半的数据进行排序,时间复杂度是 O(n(log(n))),但一般情况下时间复杂度要小的多。
//快排思路
int kthlargest(vector<int>& nums, int i, int j, int k){
int start = i;
int end = j;
int tmp;
while(start < end){
tmp = nums[start];
while(start < end && nums[end] < tmp)
end--;
nums[start] = nums[end];
nums[end] = tmp;
while(start < end && nums[start] > tmp)
start++;
nums[end] = nums[start];
nums[start] = tmp;
}
if( start == k - 1)
return nums[start];
else{
if(start < k - 1){
return kthlargest(nums, start + 1, j, k);
}else{
return kthlargest(nums, i, start - 1, k);
}
}
}
int findKthLargest(vector<int>& nums, int k){
int len = nums.size();
return kthlargest(nums, 0, len - 1, k);
}<span id="_xhe_cursor">
</span>
该题最直观的解决思路是先对数组进行排序,然后返回第k个元素即可,但是该方法的时间复杂度为 O(nlog(n)), 较高。比较高校的思路有两种:一种是堆排序的思路,一种是快拍的思路。
一、堆排序的思路。该思路设置容量为 k 的小顶堆,将剩余的元素每一个和堆顶元素进行比较,若比堆顶元素小则该元素必然不会是第 k 大的元素,直接处理下一个元素;若比堆顶元素大则说明堆顶元素不可能是第 k 大的元素,替换堆顶元素与该元素,调整堆。 每调整一次堆的时间复杂性为 O(log(k)),总共有 n 个元素,则该思路的总时间复杂度为:O(n(log(k)))。
int findKthLargest(vector<int>& nums, int k){
int len = nums.size();
int i = (k - 1 - 1)/2;
int tmp;
//调整初始堆
while(i >= 0){
int tmpi = i;
tmp = nums[i];
int j = i*2 + 1;
while(j < k){
if(j+1 < k && nums[j+1] < nums[j])
j++;
if(nums[j] >= tmp)
break;
nums[i] = nums[j];
i = j;
j = i*2 + 1;
}
nums[i] = tmp;
i = tmpi - 1;
}
//遍历剩余元素
for(int l = k; l < len; l++){
if(nums[l] <= nums[0])
continue;
nums[0] = nums[l];
tmp = nums[0];
i = 0;
int j = i*2 + 1;
while(j < k){
if(j + 1 < k && nums[j + 1] < nums[j])
j++;
if(nums[j] >= tmp)
break;
nums[i] = nums[j];
i = j;
j = i*2 + 1;
}
nums[i] = tmp;
}
return nums[0];
}
二、快排的思路。该思路根据快速排序的思路进行处理,首先选择数组首元素 A 进一次快排处理,使得比它小的元素都在其前面比它大的元素都在其后面,处理之后若 A 此时的位置在第 k 个位置,则直接返回,否则若比 k 小,则对其之后的元素进行同样的处理,若比 k 大则对其之前的元素进行同样的处理。直到某一次处理的元素其位置就在第 k 个元素的位置返回即可。该思路最坏情况下需要对一半的数据进行排序,时间复杂度是 O(n(log(n))),但一般情况下时间复杂度要小的多。
//快排思路
int kthlargest(vector<int>& nums, int i, int j, int k){
int start = i;
int end = j;
int tmp;
while(start < end){
tmp = nums[start];
while(start < end && nums[end] < tmp)
end--;
nums[start] = nums[end];
nums[end] = tmp;
while(start < end && nums[start] > tmp)
start++;
nums[end] = nums[start];
nums[start] = tmp;
}
if( start == k - 1)
return nums[start];
else{
if(start < k - 1){
return kthlargest(nums, start + 1, j, k);
}else{
return kthlargest(nums, i, start - 1, k);
}
}
}
int findKthLargest(vector<int>& nums, int k){
int len = nums.size();
return kthlargest(nums, 0, len - 1, k);
}<span id="_xhe_cursor">
</span>
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- android 代码实现控件之间的间距
- [Android]在代码里运行另一个程序的方法
- 关于指针的一些事情
- 肯特·贝克:改变人生的代码整理魔法
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 网页恶意代码的预防
- 高手写的Tracer-Flash代码调试类代码下载
- CSS代码缩写技巧
- 非主流Q-zOne代码代码搜集第1/2页
- CreateWeb.vbs 代码
- Lua中调用C++函数示例
- Lua中编译执行代码相关的函数详解
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- 更有效率的css代码编写第1/3页
- 代码中到底应不应当写注释?
- C++编写简单的打靶游戏