5.Kth Largest Element-第k大元素(中等题)

第k大元素

  1. 题目

    在数组中找到第k大的元素

    注意事项
    你可以交换数组中的元素的位置

  2. 样例

    给出数组 [9,3,2,4,8],第三大的元素是 4
    给出数组 [1,2,3,4,5],第一大的元素是 5,第二大的元素是 4,第三大的元素是 3,以此类推

  3. 挑战

    要求时间复杂度为O(n),空间复杂度为O(1)

  4. 题解

1.快排法O(nlogn)
具体参看中位数

public class Solution {
    /**
     * @param nums: A list of integers.
     * @return: An integer denotes the middle number of the array.
     */
    public int median(int[] nums) {
        return getMinK(nums,0,nums.length-1,(nums.length-1)/2);
    }

    private int getMinK(int[] nums, int left, int right, int k)
    {
        int i = left;
        int j = right;
        while (i != j)
        {
            while (nums[j] >= nums[left] && i < j)
            {
                j--;
            }
            while (nums[i] <= nums[left] && i < j)
            {
                i++;
            }
            swap(nums,i,j);
        }
        swap(nums,left,i);
        if (i == k)
        {
            return nums[i];
        }
        else if (i < k)
        {
            return getMinK(nums,i+1,right,k);
        }
        else
        {
            return getMinK(nums,left,i-1,k);
        }
    }

    private void swap(int[] nums, int i, int j)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

2.BFPRT算法

BFPTR算法仅仅是改变了快速排序Partion中的pivot值的选取,每次选择五分中位数的中位数作为pivot,这样可以使划分比较合理,已达到O(n)的时间复杂度。算法步骤如下:
a.将数组以每组5个元素进行划分,且至多只有一个组由n%5个元素组成。
b.对每组进行插入排序,然后选出中位数并和数组的首位元素进行换位。
c.对于所有组中的中位数进行递归找到中位数的中位数。
d.以中位数的中位数为pivot进行快速排序查找。
维基链接

class Solution
{
    /*
     * @param k : description of k
     * 
     * @param nums : array of nums
     * 
     * @return: description of return
     */
    public int kthLargestElement(int k, int[] nums)
    {
        return BFPTR(nums, 0, nums.length - 1, nums.length - k + 1);
    }

    void InsertSort(int a[], int l, int r)
    {
        for (int i = l + 1; i <= r; i++)
        {
            if (a[i - 1] > a[i])
            {
                int t = a[i];
                int j = i;
                while (j > l && a[j - 1] > t)
                {
                    a[j] = a[j - 1];
                    j--;
                }
                a[j] = t;
            }
        }
    }

    int FindMid(int a[], int l, int r)
    {
        if (l == r)
        {
            return l;
        }
        int i = l;
        int n = 0;
        for (; i < r - 5; i += 5)
        {
            InsertSort(a, i, i + 4);
            n = i - l;
            swap(a, l + n / 5, i + 2);
        }

        InsertSort(a, i, r);
        swap(a, l + n / 5, (i + r + 1) / 2);
        n /= 5;
        return n == l ? 1 : FindMid(a, l, l + n);
    }

    int Partion(int a[], int l, int r, int p)
    {
        swap(a, p, l);
        int i = l;
        int j = r;
        int pivot = a[l];
        while (i < j)
        {
            while (a[j] >= pivot && i < j)
                j--;
            a[i] = a[j];
            while (a[i] <= pivot && i < j)
                i++;
            a[j] = a[i];
        }
        a[i] = pivot;
        return i;
    }

    int BFPTR(int a[], int l, int r, int k)
    {
        int p = FindMid(a, l, r); 
        int i = Partion(a, l, r, p);
        int m = i - l + 1;
        if (m == k)
        {
            return a[i];
        }
        else if (m > k)
        {
            return BFPTR(a, l, i - 1, k);
        }
        return BFPTR(a, i + 1, r, k - m);
    }

    private void swap(int[] nums, int i, int j)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
};

Last Update 2016.9.20

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值