无序数组前K个最大数

思路:使用前K个元素建立一个K个元素的小顶堆,然后遍历数组后面的内容替换堆顶并保持小顶堆。

/* 
参考链接:https://github.com/yxjxx/SortAlgorithmsEx/blob/master/SortAlgs/yj_quick_sort.cpp
https://blog.csdn.net/BRO_BMW/article/details/105985158
*/

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];   

    NSArray *arr = @[@22, @4, @7, @1, @2, @3, @5, @3, @6, @3, @2, @18, @7];
    NSArray *n = [self findK:arr k:5];
    NSLog(@"%@", n);//(6,7,7,18,22)
}

- (NSArray<NSNumber *> *)findK:(NSArray *)arr k:(int)k{
    NSMutableArray *heap = [self quickSortFirstK:arr k:k];
    for (int i = k; i<arr.count; i++) {
        if ([arr[i] intValue] > [heap[0] intValue]) {
            heap[0] = arr[i];
            [self heapify:heap idx:0];
        }
    }
    return heap;
}

//节点 i 的左子节点下标2i+1, 右子节点下标2i+2
- (void)heapify:(NSMutableArray *)arrM idx:(int)idx{
    if (idx*2 + 1 > arrM.count-1) {
        return;
    }
    if ([arrM[idx] intValue] > [arrM[2*idx+1] intValue]) {
        [self swapIndexA:idx indexB:2*idx+1 arrM:arrM];
        [self heapify:arrM idx:2*idx+1];
        if ((2*idx+2) <= arrM.count-1 && [arrM[idx] intValue] > [arrM[2*idx+2] intValue]) {
            [self swapIndexA:idx indexB:2*idx+2 arrM:arrM];
            [self heapify:arrM idx:2*idx+2];
        }
    } else if ((2*idx+2) <= arrM.count-1 && [arrM[idx] intValue]> [arrM[2*idx+2] intValue]) {
        [self swapIndexA:idx indexB:2*idx+2 arrM:arrM];
        [self heapify:arrM idx:2*idx+2];
    }
    return;
}

- (void)swapIndexA:(int)a indexB:(int)b arrM:(NSMutableArray *)arrM {
    NSNumber *temp = arrM[a];
    arrM[a] = arrM[b];
    arrM[b] = temp;
}

- (NSMutableArray *)quickSortFirstK:(NSArray *)arr k:(int)k {
    NSArray *subArr = [arr subarrayWithRange:NSMakeRange(0, k)];
    NSMutableArray *arrM = [subArr mutableCopy];
    [self quickSort:arrM start:0 end:k-1];
    return arrM;
}

- (void)quickSort:(NSMutableArray *)arrM start:(int)start end:(int)end {
    if (start >= end) {
        return;
    }//递归结束条件
    int pivot = [arrM[start] intValue];
    int left = start;
    int right = end;
    while (left < right) {
        while (left < right && [arrM[right] intValue] > pivot) {
            right--;
        }
        if (left < right) {
            arrM[left] = arrM[right];
            left++;
        }
        
        while (left < right && [arrM[left] intValue] < pivot) {
            left++;
        }
        
        if (left < right) {
            arrM[right] = arrM[left];
            right--;
        }
    }
    arrM[left] = @(pivot);
    
    [self quickSort:arrM start:start end:left-1];
    [self quickSort:arrM start:left+1 end:end];
}

@end