zoukankan      html  css  js  c++  java
  • 为什么基于快排的查找第k大数时间复杂度是O(n)

    我们都知道,查找第k大数有一个很常用的方法,是基于快排的查找,思路跟快排基本一样,代码如下:

        public int findKthLargest(int[] nums, int k) {
            return (findKthNum(nums,0,nums.length-1,k-1));
        }
    
        private int findKthNum(int[] nums, int left, int right, int k){
            int stan = nums[right];
            int i = left, j = right;
            if (left == right && left == k) {
                return nums[left];
            }
            else {
                while (i < j) {
                    while (i < j && nums[i] >= stan) {
                        i++;
                    }
                    while (i < j && nums[j] <= stan){
                        j--;
                    }
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
            nums[right] = nums[i];
            nums[i] = stan;
            if (k < i) {
                return findKthNum(nums, left, i - 1, k);
            }
            else if (k > i) {
                return findKthNum(nums, i + 1, right, k);
            }
            else {
                return nums[i];
            }
        }

    因为每次分割完只需要继续操作一边,所以时间复杂度是O(n)。

    但光是这样解释让人有点不清楚,不通过计算很难让人明白为什么是O(n),比如,即便每次只操作一边,那么遍历的次数也是logn次,每次遍历是O(n),很容易让人误解为该方法是O(nlogn)。

    所以这里还是要回到时间复杂度专门的递推公式上来。

    我们都知道,快速排序的理想以及平均时间复杂度是O(nlogn),其递推公式如下,跟归并排序基本无异,只是多了一个在理想或者平均的限制,因为快排的最坏是O(n^2)

    平均情况下:T(n)=2*T(n/2)+n;      第一次划分
    
          =2*(2*T(n/4)+n/2)+n;     第二次划分  (=2^2*T(n/4)+2*n)
    
          =2*(2*(2*T(n/8)+n/4)+n/2)+n;     第三次划分(=2*3*T(n/8)+3*n)
    
          =.....................
    
          =2^m+m*n;  第m次划分
    
    因为2^m=n,所以等价于 = n+m*n
    所以m=logn,所以T(n)=n+n*logn;     

    这边还是比较好理解的,那么基于快排的查找第k大数的时间复杂度如下:

    平均情况下:T(n) = T(n/2) + n;      第一次划分
    
          = T(n/4) + n/2 + n;     第二次划分  
    
          = T(n/8) + n/4 +n/2 +n;     第三次划分
    
          =.....................
    
          = T(n/n) + 2 + 4 + ... + n;  第m次划分
    
    是一个等比数列的求和公式,那么显然T(n) = 2n

    所以计算时间复杂度最好严谨按照递推公式来,那么这里注意基于快排查找第k大数,也是平均时间复杂度为O(n)。

    《算法导论》介绍到一个最坏情况下也是O(n)的方法,这里不做详细介绍,参考http://blog.chinaunix.net/uid-26456800-id-3407406.html

  • 相关阅读:
    mysql "The user specified as a definer ('root'@'%') does not exist" 问题
    mysql添加Federated引擎问题
    D7经典脚本[multi/handler]
    redhat7.4安装vertica-9.1.0教程
    批量在当前目录下所有的文件中添加指定字段
    mysql 水平分表技术
    linux普通用户提权
    两步完成利用procdump64+mimikatz获取win用户密码
    hibernate中对象的三种状态分析
    Hibernate 入门案例
  • 原文地址:https://www.cnblogs.com/liusandao/p/12512391.html
Copyright © 2011-2022 走看看