Leetcode算法题215:数组中第k大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

思路1:快排思想
快速排序是对冒泡的改进,降低冒泡的递归深度, 使时间复杂度降低到O(nlgn)。因为快排每次将数组划分为两组加一个基准元素,每一趟划分你只需要将k与基准元素的下标进行比较。
如果比基准元素下标大就从右边的子数组中找,如果比基准元素下标小从左边的子数组中找,如果一样则就是基准元素,找到,
如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。

- (int)findKthLargest:(NSMutableArray *)array k:(int)k {
    int i = 0;
    int j = (int)array.count - 1;
    while (true) {
        int temp = [self partition:array i:i j:j];//执行一遍后,把最大的放最前面,再比较temp和k的关系
        if (k == temp + 1) {
            return [array[temp] intValue];
        }else if(k < temp + 1)
        {
            j = temp-1;//这里每次要把基准元素去掉,否则会死循环
        }
        else
        {
            i = temp + 1;
        }
    }
}

- (int)partition:(NSMutableArray *)array i:(int)i j:(int)j {
    int pivot = [array[i] intValue];
    while (i != j) {
        while (i < j && [array[j] intValue] < pivot) {
            j--;
        }
        while (i < j && [array[i] intValue] > pivot) {
            i++;
        }
        if (i < j) {
            [array exchangeObjectAtIndex:i withObjectAtIndex:j];
        }
    }
    return i;
}

思路2:堆排序思想
建立最小根堆,用数组的前k个数,建立最小根堆。然后从第k+1开始,和堆顶比较,如果比堆顶大,就交换,交换完重新维护成最小根堆,直到结束。这样堆里存放的就是数组中前k个最大的元素,而堆顶就是这里面最小的,也就是第k大的元素。

- (int)findKthLargest:(NSMutableArray *)array k:(int)k {
    
    // 1.前k个数建立最小根堆,最小的数在堆顶
    NSMutableArray *newArr = [self buildHeap:[array subarrayWithRange:NSMakeRange(0, k)].mutableCopy n:k];
    // 2.从第k+1个开始,和堆顶比较
    for (NSInteger i = k; i < array.count; i++) {
        // 3.比堆顶大,则交换
        if ([array[i] intValue] > [newArr[0] intValue]) {
            newArr[0] = array[i];
            // 4.再对数组进行堆排序
            newArr = [self buildHeap:newArr n:k];
        }
    }

    return [newArr[0] intValue];
}

- (NSMutableArray *)buildHeap:(NSMutableArray *)array n:(NSInteger)n {
    NSInteger last = n - 1;
    NSInteger parent = (last - 1) / 2;
    for (NSInteger i = parent; i >= 0; i--) {
        [self heapify:array n:n i:i];
    }
    return array;
}

// heapify:小根堆思想,最小的放根位置
- (void)heapify:(NSMutableArray *)array n:(NSInteger)n i:(NSInteger)i {
    if (i >= n) {
        return;//递归出口
    }
    
    // 完全二叉树,根节点位置为i
    // 左子节点
    NSInteger c1 = 2*i + 1;
    NSInteger c2 = 2*i + 2;
    NSInteger min = i;
    
    if (c1 < n && [array[c1] intValue] < [array[min] intValue]) {
        min = c1;
    }
    if (c2 < n && [array[c2] intValue] < [array[min] intValue]) {
        min = c2;
    }
    if (min != i) {
        [array exchangeObjectAtIndex:min withObjectAtIndex:i];
        [self heapify:array n:n i:min];
    }
}

思路3:java的优先队列PriorityQueue
优先级队列,常用来代替堆,每次直接加入新数即可,自动维护大小顺序,最小的数在堆顶。数组中前k个元素加入到队列中,当k+1个进入后,最小的出队,这样数组遍历完后,队列中刚好剩下k个元素,返回堆顶元素就是第k大的元素

 public int findKthLargest(int[] nums, int k) {
     PriorityQueue<Integer> queue = new PriorityQueue<>();
     for (num:nums) {
         queue.offer(num);//入队
         if (queue.size() > k) {
             queue.poll();//堆顶最小的元素出队
         }
     }
     return queue.peak();//返回堆顶最小的元素
 }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355