【二叉树】数据流中的第 K 大元素

0x00 题目

设计一个找到数据流中第 k 大元素的类(class)
注意是排序后的第 k 大元素,不是第 k 个不同的元素

请实现 KthLargest 类:

KthLargest(int k, int[] nums)
使用整数 k 和整数流 nums 初始化对象

int add(int val)
val 插入数据流 nums 后,返回当前数据流中第 k 大的元素


0x01 思路

方法一:
先对初始化的数组进行排序
nums.sorted()
时间复杂度:O(NlogN) (快排)

插入新数据时,使用二分搜索法,找到对应的位置,然后插入
nums.insert(val, at: index)

最后返回指定位置的值
nums[nums.count - k]


方法二:
使用小顶堆进行数据管理

小顶堆:
每个结点的值都 小于或等于 其左右子节点的值

其实就是利用完全二叉树的结构来维护的一维数组

用公式来描述小顶堆就是:
arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

构建一个包含 k 个元素的小顶堆
堆顶就是第 k 大的元素


0x02 解法

语言:Swift

解法:

class KthLargest {
	// 存储 k 个元素
    private var arr: [Int] = []
    private var k: Int = 0
    
    init(_ k: Int, _ nums: [Int]) {
        self.k = k
        for num in nums {
            _ = add(num)
        }
    }
    
    func add(_ val: Int) -> Int {
    	// 不够 k 个元素,继续添加
        if arr.count < k {
            arr.append(val)
            // 添加元素是追加到末尾,然后进行 "上浮" 操作,把小元素 "浮" 到上面去
            minHeapFixup(&arr)
        }else{
        	// 已经有 k 个元素了,进行判断
            if val > arr[0]  {
            	// 大于就替换,堆顶元素
                arr[0] = val
            }
            // 替换后,然后进行 "下沉" 操作,把大元素 "沉" 到下面去
            minHeapFixdown(&arr, 0, k)
        }
        return arr[0]
    }
    
    //  "上浮" 操作
    private func minHeapFixup(_ arr: inout [Int]) {
        var j = arr.count - 1
        // 索引 (j-1)/2 的节点,是索引 j 节点,的父节点
        // 小的元素 "上浮",然后再比较 父节点 与 父节点的父节点
        while (j-1)/2 >= 0 && arr[j] < arr[(j-1)/2] {
            arr.swapAt(j, (j-1)/2)
            j = (j-1)/2
        }
    }
    
    // "下沉" 操作
    private func minHeapFixdown(_ arr: inout [Int], _ i: Int, _ n: Int) {
        var p = i // 父节点索引
        let count = arr.count
        
        while true {
            var min = p

            // 根节点与左节点比较,如果大于左节点,记录索引
            if p*2+1 < count && arr[p] > arr[p*2+1] {
                min = p*2 + 1
            }
            
            // 上一步比较的结果 与 右节点比较,如果大于右节点,记录索引
            if p*2+2 < count && arr[min] > arr[p*2+2] {
                min = p*2+2
            }
            // 索引未改变,结束
            if min == p {
                break
            }
            // 交换,进行下一轮
            arr.swapAt(min, p)
            p = min
        }
    }
}

0x03 我的小作品

欢迎体验我的作品之一:小五笔86版应用
五笔学习好帮手
App Store 搜索即可~


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豪冷啊

你的鼓励是对我的认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值