数组中第K大的数

寻找第K大

http://www.nowcoder.com/questionTerminal/e016ad9b7f0b45048c58a9f27ba618bf

题目描述

有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。

思路:快排 + 二分
用快速排序思想把数组按降序排列,第K大元素的下标就是 targetPos = K-1
(如果按升序排列数组,第K大元素的下标就是n - K,代码要稍微改动一下,但思想都一样,看哪个更顺手了)
每次partition后数组被分为三段:a[0...pivot-1], a[pivot], a[pivot + 1, end]
比较pivot 和 targetPos的大小,若相等则返回a[pivot];
若不相等(大小关系看代码),这时就可以排除数组的一半了,则递归调用quickSort排序数组的剩余目标位置

时间复杂度:每次排除一半的元素,partition比较加交换需要操作n次,则 n + n/2 + n/4 + ... + 1,这是公比为1/2的等比数列,
Sn = a1(1 - q^n)/ (1 - q), 带入数字得2n
所以 时间复杂度为 O(n)

降序排列数组

import java.util.*;
//时间复杂度O(n)
//
public class Finder {
    public int findKth(int[] a, int n, int K) {
        // write code here
        int targetPos = K - 1;
        return quickSort(a, 0, n-1, targetPos);
    }
    private int quickSort(int[] a, int start, int end, int pos) {
        int pivot = partition(a, start, end);
        if (pivot == pos)
            return a[pos];
        else if (pivot < pos) 
            return quickSort(a, pivot + 1, end, pos);
        else
            return quickSort(a, start, pivot - 1, pos);
    }
    private int partition(int[] a, int start, int end) {
        int pivot = end;
        int count = start;
        for (int i = start; i < end; i++) {
            if (a[i] > a[pivot]) {
                swap(a, i, count++);
                //count++;
            }
        }
        swap(a, count, pivot);
        return count;
    }
    private void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}

升序排列数组

import java.util.*;

public class Finder {
    public int findKth(int[] a, int n, int K) {
        // write code here
        int targetPos = n - K;
        return quickSort(a, 0 , n-1, targetPos);

    }
    private int quickSort(int[] a, int start, int end, int pos) {
        int pivot = partition(a, start, end);
        if (pivot == pos)
            return a[pos];
        else if (pivot < pos)
            return quickSort(a, pivot + 1, end, pos);
        else
            return quickSort(a, start, pivot - 1, pos);
    }
    private int partition(int[] a, int start, int end) {
        int pivot = end;
        int count = start;
        for (int i = start; i < end; i++) {
            if (a[i] < a[pivot]) {
                swap(a, i, count);
                count++;
            }
        }
        swap(a, count, pivot);
        return count;
    }
    private void swap(int[] a, int i, int j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}
全部评论

相关推荐

背景&nbsp;双一流本硕&nbsp;双非大圆满&nbsp;只找游戏开发相关的岗位。&nbsp;8&nbsp;月初开始秋招到现在&nbsp;投了四五十家吧,&nbsp;目前两&nbsp;offer,&nbsp;不打算继续投了,把剩下的流程走完就开始沉淀了。目前两&nbsp;offer&nbsp;一个是网易互娱测开&nbsp;base&nbsp;广州,一个是江娱互动客户端开发&nbsp;base&nbsp;北京。应该确定网易这个了,说实话北京这个我挺想去的,这家的产品和工作氛围我了解了也不错,是那种踏实做事的,可惜我是广东人。网易的测开是调剂的二志愿,看了下有内部转岗机会,所以打算后面找个时间提前实习,沉淀下再做一个&nbsp;demo&nbsp;作品,写一些&nbsp;shader,增强下图形学渲染的能力,再学点编辑器开发。看到时候内部转岗或者春招继续投客户端开发这样。后面还能再动摇的话应该就灵犀或者腾子了吧(假如这两家确认的是客户端开发岗的话)。-----------------------补下timeline网易互娱&nbsp;测开&nbsp;8.2笔试&nbsp;&nbsp;8.21&nbsp;技术面&nbsp;&nbsp;8.29&nbsp;leader&amp;HRBP面(终面)&nbsp;9.8&nbsp;录用审核(之前一直显示面试中)9.14&nbsp;oc江娱互动&nbsp;客户端开发&nbsp;8.29主程面&nbsp;9.3&nbsp;制作人面&nbsp;9.5&nbsp;BOSS面&nbsp;9.11&nbsp;口头OC&nbsp;9.15&nbsp;正式offer后面考虑了一下&nbsp;&nbsp;感觉还是能走开发就开发吧,测开不太感兴趣,要内部活水转岗还要满1年才能申请。。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务