【LeetCode】215. Kth Largest Element in an Array,基于Java和C++的解法

原创 2016年05月31日 11:40:47

215. Kth Largest Element in an Array

Total Accepted: 57859 Total Submissions: 171725 Difficulty: Medium

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.

For example,
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.

【Section one】分析

题意输入一个未排序的数组,寻找第K大的数并返回。初见之下,这个题似乎比较简单,但实际操作中遇到一些有趣的问题:

      1、采用Java,Accepted的算法,用C++实现出现了内存超限(Memory Limit Exceed);

      2、Java和C++不同的内存管理模式;

分析:

     寻找数组中第K大的数据,一个直观的思路是将数组排序,然后直接通过索引返回第K大的数据。这样做完全可以实现,但是明显做了很多无用功,由于我们只需寻找第K大的数,完全没有必要进行全排序。在所有基本的排序算法中,快速排序是一种比较优秀的算法,平均时间复杂度O(nlogn),在排序中用到的一个重要思想:分治!每一次partition时,返回的都是分割后作为“”的元素的下标,其左边的元素均小于等于它,其右边的元素均大于它,因此,经过分割后,若“”元素在数组中的下标为p,则“”元素为第lengthOfArray-p大的元素;基于这种思想我们可以很快写出两种风格的程序。

【Section two】

基于Java语言的解法一:

class Solution {
    public int findKthLargest(int[] nums, int k) 
    {
    	return quickSort(0,nums.length-1,nums,k);        
    }
    
    int quickSort(int low,int high,int[] temp,int k)
    {
    	if(low>=high)return temp[low];//递归结束的约束条件
    	int point=partition(low,high,temp);//每一次分割后“轴”的下标
    	
    	if(temp.length-point==k) return temp[point];
    	else if(temp.length-point>k){
    		return quickSort(point+1,high,temp,k);
    	}
    	else{
    		return quickSort(low,point-1,temp,k);
    	}
    }
    
    public int partition(int low,int high,int[] temp)//采用分治的思想
    {
    	int cur=temp[low];
    	while(low<high)
    	{
    		while(low<high&&temp[high]>=cur)
    			--high;
    		temp[low]=temp[high];
    		while(low<high&&temp[low]<=cur)
    			++low;
    		temp[high]=temp[low];
    	}
    	temp[low]=cur;
    	return low;
    }
}

基于Java的解法二:

   这个解法与解法一相比,都是“分治”的思想,但是,解法二中却消耗了大量的内存!!!!,随着递归的进行,每一层都需要分配内存用于存储子数组,且此题给定的形参为int[],而根据需要我们定义的是具有动态增删功能的数组列表,在递归调用的时候,还需要复杂的转化,这也会造成时间和空间的消耗。

class Solution2 {
    public int findKthLargest(int[] nums, int k) 
    {
        List<Integer> leftarray=new ArrayList<Integer>();
        List<Integer> rightarray=new ArrayList<Integer>();//定义两个数组列表存储分割后的数组
       
        for(int i=1;i<nums.length;i++)
        {
            if(nums[i]<=nums[0])//以第一个元素为轴,将数组分成两个子数组
            {
            	leftarray.add(nums[i]);//左数组为小于等于转轴的元素
            }
            else
            {
            	rightarray.add(nums[i]);
            }
        }
        
        if(rightarray.size()>=k)//此情况下,第k大的元素必然存在于右子树组
        {
        	int[] rightRemain=new int[rightarray.size()];
        	int i=0;
        	for(Integer e:rightarray)//由于给定的方法的形参列表为int[],这里需要转换一下
        		rightRemain[i++]=e;
        	return findKthLargest(rightRemain, k);
        }
        else if(rightarray.size()==k-1)
        {
        	return nums[0];
        }
        else
        {
        	int[] leftRemain=new int[leftarray.size()];
        	int i=0;
        	for(Integer e:leftarray)
        		leftRemain[i++]=e;
        	return findKthLargest(leftRemain, k-rightarray.size()-1);
        }
       
    }
}

</pre><p></p><pre>

基于C++的解法:

     如下为基于C++的解法,和基于Java的解法二完全相同,看上去程序更为简洁,但是,在LeetCode平台上会出现内存超限(Memory Limit Exceeded)的问题,这与C++中内存的管理模式有关:vector其中一个特点:内存空间只会增长,不会减小,援引C++ Primer:为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。

    同时,vector的clear()方法只能清除vector中的元素却无法释放其占用内存,一般通过vector<int>().swap(p)来释放。swap()是交换函数,使vector离开其自身的作用域,从而强制释放vector所占的内存空间。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k)
    {
        vector<int> leftArray;
        vector<int> rightArray;
        
        for(int i=1;i<nums.size();i++)
        {
            if(nums[i]<=nums[0])
            leftArray.push_back(nums[i]);
            else
            rightArray.push_back(nums[i]);
        }
        
        if(rightArray.size()>=k)
        {
            vector<int>(leftArray).swap(leftArray);
            return findKthLargest(rightArray, k);
        }
        else if(rightArray.size()==k-1)
        {
            return nums[0];
        }
        else
        {
            int len=k-rightArray.size()-1;
            vector<int>().swap(rightArray);
            return findKthLargest(leftArray, len);
        }
    }
};




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【LeetCode-面试算法经典-Java实现】【215-Kth Largest Element in an Array(数组中第K大的数)】

【215-Kth Largest Element in an Array(数组中第K大的数)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】代码下载【https://github...

LeetCode(215) Kth Largest Element in an Array

题目Find the kth largest element in an unsorted array. Note that it is the kth largest element in the ...

LeetCode-215.Kth Largest Element in an Array

https://leetcode.com/problems/kth-largest-element-in-an-array/ Find the kth largest element in an ...

【leetcode】215. Kth Largest Element in an Array

【leetcode】215. Kth Largest Element in an ArrayFind the kth largest element in an unsorted array. Not...

Leetcode 215. Kth Largest Element in an Array[medium]

题目: Find the kth largest element in an unsorted array. Note that it is the kth largest element in t...

LeetCode 215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so...

Leetcode 215 Kth Largest Element in an Array 数组中第k大的元素

在一个无须数组中找出第k大的元素。

[LeetCode 215]Kth Largest Element in an Array (分治法/快速排序)

215. Kth Largest Element in an ArrayFind the kth largest element in an unsorted array. Note that it ...
  • zlasd
  • zlasd
  • 2016-09-14 21:07
  • 207

LeetCode 215 Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so...

算法设计Week2 LeetCode Algorithms Problem #215 Kth Largest Element in an Array

题目描述: Find the kth largest element in an unsorted array. Note that it is the kth largest element i...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)