数组中第K大的元素

数组中第K大的元素总结

解法1: 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k)。

解法2: 如果k很小,比如第五个最大的数,而整个数组的长度非常的大,那么,还有一种方法就是,我做k遍找最大的数,每做一遍,就把最大的放在数组的最后面(遍历一次找出最大的数例如冒泡,选择排序都可以。),然后减少数组扫描的范围,就可以把第k大的数找出来,这样做的复杂度就是O(K*N),在K很小的情况下,还是不错的。

解法3: 利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。第K大的元素在已排序数组中的下标应为index(第K大元素)=数组长度-1。记元素X的下标为index(x),当index(x)= index(第K大元素),表示找到结果,返回。

这时有两种情况:

1. index(x)> index(第K大元素),则继续在下标index(x)的左边找

2. index(x)> index(第K大元素),则继续在下标index(x)的右边找

解法4: 二分[Smin,Smax]查找结果X,统计X在数组中出现,且整个数组中比X大的数目为k-1的数即为第k大数。时间复杂度平均情况为O(n*logn)

解法5:用O(4*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)

解法6:维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)

解法7:利用计数排序的思想,,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)。

像解法3和6应该是比较常见的解法:

下面是解法3的java代码

package com.wj;

/**
 * Created by wangjia .
 * Date:2015/9/5 0005
 * Time:10:53
 */
public class MaxK {
    /*找到划分点位置*/
    int Sort(int[] arr, int low, int high) {
        int pivot = arr[low]; //这里每次的枢纽元素都取了待排数组的第一个元素,记住是a[low],而不是a[0]
        System.out.println("low-->"+low);
        while (low < high)  //时间复杂度是O(n),n是数组长度
        {
            while (arr[high] >= pivot && low < high){
                high--;
            }
            if(low<high){
                arr[low++] = arr[high];
            }
            while (arr[low] < pivot && low < high){
                low++;
            }
            if(low<high){
                arr[high--] = arr[low];
            }
        }
        arr[low] = pivot;
        System.out.println("low-->"+low);
        return low;
    }

    int QuickSort_K_MAX(int[] arr, int low, int high, int k) {
        if (low >= high) {
            return arr[low];
        }
        int res=0;
        int mid = Sort(arr, low, high); //划分子递归数组
        System.out.println("mid-->"+mid);
        if(mid==k){
            res= arr[mid];
        }else if (mid > k) {
             res=QuickSort_K_MAX(arr, low, mid - 1, k); //左递归
        }else {
             res=QuickSort_K_MAX(arr, mid + 1, high, k); //右递归,一旦右递归mid+1=high,将退化成冒泡,递归深度将变成n,n为数组长度
        }
        return res;
    }

   public  int getK(int[] arr,int k){
        return QuickSort_K_MAX(arr,0,arr.length-1,arr.length-k);
   }
}
//时间复杂度:接近O(N)

测试代码:

package com;

import com.wj.MaxK;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/** 
 * MaxK Tester. 
 * Created by wangjia .
 * Date:09/05/2015
 * Time:$Time
 *
*/ 
public class MaxKTest { 
    private MaxK instance;
    @Before
    public void before() throws Exception { 
        instance=new MaxK();
    }
    @After
    public void after() throws Exception { 
        instance=null;
    }
    @Test
    public void testGetK() throws Exception { 
        int[] arr={4, 5, -1, 2, 3};
        Assert.assertEquals(-1,instance.getK(arr, 5));
        Assert.assertEquals(5,instance.getK(arr, 1));
        Assert.assertEquals(4,instance.getK(arr, 2));
        Assert.assertEquals(3,instance.getK(arr, 3));
        Assert.assertEquals(2,instance.getK(arr, 4));
        int[] arr2={-8,11,4,-2,44,56565,23,-232};

        Assert.assertEquals(56565,instance.getK(arr2, 1));
        Assert.assertEquals(44,instance.getK(arr2, 2));
        Assert.assertEquals(-232,instance.getK(arr2, 8));
    }
}

解法6下次再来。

另外给出一些其他的参考文章:http://blog.csdn.net/beiyeqingteng/article/details/6992290

http://job.xdnice.com/content/BiShiJingYan/2012-11/3971.htm

时间: 2024-11-02 00:23:09

数组中第K大的元素的相关文章

找一个数组中第K大的数

快排思想,选取序列的一个key进行划分,小于key的分在左边,大于key的在右边,key的位置-low+1就是最后一个元素是key的序列中元素的数量,当元素数量大于K时,就在左半部分递归找,等于时 arr[key]就是第K 大的元素,小于K时,在右边递归找第k-num大的元素 /** * 文件名:FindK.java * 时间:2014年11月7日上午11:23:43 * 作者:修维康 */ package chapter7; /** * 类名:FindK 说明:找到一个数组中第K大的元素 */

leetcode | Median of Two Sorted Arrays 寻找2个有序数组中第k大的值

问题 Median of Two Sorted Arrays There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log(m + n)). 分析 本题更经典通用的描述方式时: 给定2个有序数组,找出2个数组中所有元素中第k大的元素. 思路1 直观思

挑战面试编程:查找数组中第k大的数

查找数组中第k大的数 问题: 查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思路: 1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. 只需找到第k大的数,不必把所有的数排好序.我们借助快速排序中partition过程,一般情况下,在把所有数都排好序前,就可以找到第k大的数.我们依据的逻辑是,经过一次partition后,数组被pivot分成左右两部分:S左.S右.当S左的元素个数|S左|等于k-1时,pivo

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

[215-Kth Largest Element in an Array(数组中第K大的数)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 代码下载[https://github.com/Wang-Jun-Chao] 原题 Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth d

[经典算法题]寻找数组中第K大的数的方法总结

[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据中查找到第k个大的值. 名称是:设计一组N个数,确定其中第k个最大值,这是一个选择问题,当然,解决这个问题的方法很多,本人在网上搜索了一番,查找到以下的方式,决定很好,推荐给大家. 所谓"第(前)k大数问题"指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题.

[LeetCode] Kth Largest Element in an Array 数组中第k大的数字

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'

查找无序数组中第K大的数

思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> #include <cstdio>5 using namespace std; int findK(int left, int right, int arr[], int k) { if(left >= right) return arr[left]; int first = left, la

求数组中第k大的数(分治法)

思想:快排 因为单趟排序是使选定的king值到其应该到的位置,所以每次判断这个king的正确位置是否是第K大数的位置即可 #include <iostream> using namespace std; //快排中的单趟排序 int PartSort(int* arr,int start,int end) { int first = start; int last = end; int tmp = arr[first]; int key = first; while (first < l

215. Kth Largest Element in an Array找出数组中第k大的值

堆排序做的,没有全部排序,找到第k个就结束 public int findKthLargest(int[] nums, int k) { int num = 0; if (nums.length <= 1) return nums[0]; int heapSize = nums.length; //1.构建最大堆 int half = (heapSize-2)/2; for (int i = half;i >= 0;i--) { adjust(nums,heapSize,i); } while