04 -- 数组中第K个最大元素

数组中第K个最大元素

Github算法刷题一千零一夜,欢迎star

  • top – K 问题,思路一般就是建堆
  • 求最大,就建大顶堆
  • 求最小,就建小顶堆
  • 求第K个,就删除堆顶元素(k-1)次
  • 答案就是删除(k-1)次后,堆顶元素的值

>

  • 需要会自己建堆操作,上溢操作,下溢操作
  • 关键点:
    1)父节点和子节点的计算方法,这个需要自己推导,死记硬背没用的
    2)下溢操作的时候,父节点需要和左右分别进行比较,比较完后再决定是否交换值
import Foundation
/**
 输入: [3,2,1,5,6,4] 和 k = 2
 输出: 5
 */

/**
 用 let resArr = nums.sorted(by: >)
 return resArr[k-1]
 
 这种也是可以的,但是这个不是考点
 
 考点: 建堆, 上溢, 下溢
 求第k个最大,就是把顶部元素,删除k-1次,每删除一次后,重新调整堆
 */
class xiapi_04 {
    func findKthLargest(_ nums: [Int], _ k: Int) -> Int {
        
        
        let heap = Heap(k, nums)
        heap.createHeap()
        
        for _ in 0..<k-1 {
            heap.removeTop()
        }
        
        return heap.heapArr[0]
    }
}

class Heap {
    var k: Int
    var arr = [Int]()
    var heapArr = [Int]()
    
    init(_ k: Int, _ arr: [Int]) {
        self.k = k
        self.arr = arr
    }
    
    func createHeap() {
        for i in 0..<arr.count {
            heapArr.append(arr[i])
            siftUp(heapArr.count - 1)
        }
    }
    
    func siftUp(_ index: Int) {
        if index > 0 {
            let parent = (index - 1) / 2
            if heapArr[index] >= heapArr[parent] {
                heapArr.swapAt(index, parent)
                siftUp(parent)
            }
        }
    }
    
    func removeTop() {
        heapArr.swapAt(0, heapArr.count - 1)
        heapArr.removeLast()
        siftDown(0)
    }
    
    func siftDown(_ index: Int) {
        var nextReplaceIndex = index
        let left = index * 2 + 1
        let right = left + 1
        
        // 注意这里,左右都进行比较一次,先不交换
        if left < heapArr.count && heapArr[nextReplaceIndex] <= heapArr[left] {
            nextReplaceIndex = left
        }
        
        if right < heapArr.count &&  heapArr[nextReplaceIndex] <= heapArr[right] {
            nextReplaceIndex = right
        }
        
        // 如果发现需要调整顺序,再开始交换
        if nextReplaceIndex != index {
            heapArr.swapAt(nextReplaceIndex, index)
            siftDown(nextReplaceIndex)
        }
        
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值