数组算法之【数组中第K个最大元素】

目录

LeetCode-215题


LeetCode-215题

给定整数数组nums和整数k,返回数组中第k个最大元素

java 复制代码
public class Solution {
    /**
     * 这里是基于小顶堆这种数据结构来实现的
     */
    public int findKthLargest(int[] nums, int k) {
        // 实例化一个小顶堆
        MinHeap minHeap = new MinHeap(k);

        // 往小顶堆中添加k个元素
        for (int i = 0; i < k; i++) {
            minHeap.offer(nums[i]);
        }

        // 添加k个元素之后
        for (int i = k; i < nums.length; i++) {
            // 遇到不大于堆顶元素的直接跳过不管,继续下一个
            if (nums[i] <= minHeap.peek()) {
                continue;
            }
            // 遇到大于堆顶元素的就将其把堆顶元素替换
            minHeap.replace(nums[i]);
        }

        // 此时堆顶元素就是第k个最大元素
        return minHeap.peek();
    }

    /**
     * 自定义一个小顶堆
     */
    private static class MinHeap {
        private final int[] container;
        private int size;

        public MinHeap(int capacity) {
            container = new int[capacity];
        }

        /**
         * 添加元素
         */
        public boolean offer(int num) {
            if (size == container.length)
                return false;
            // 执行上浮操作
            siftUp(num);
            return true;
        }

        /**
         * 上浮
         */
        private void siftUp(int num) {
            int child = size++;
            // 通过子节点找父节点位置
            int parent = (child - 1) >> 1;
            // 只要满足条件就一直找并比较
            while (child > 0 && container[parent] > num) {
                container[child] = container[parent];
                child = parent;
                parent = (child - 1) >> 1;
            }
            // 新添加的元素放到合适的位置
            container[child] = num;
        }

        /**
         * 替换顶部元素
         */
        public void replace(int num) {
            container[0] = num;
            // 执行下潜操作
            siftDown(0);
        }

        /**
         * 下潜
         */
        private void siftDown(int parent) {
            // 通过父节点位置找左子节点和右子节点的位置
            int left = (parent << 1) + 1;
            int right = left + 1;

            // 只要满足有任一子节点的值小于父节点的值就交换顺序
            int min = parent;
            if (left < size && container[left] < container[min]) {
                min = left;
            }
            if (right < size && container[right] < container[min]) {
                min = right;
            }
            if (min != parent) {
                swap(parent, min);
                siftDown(min);
            }
        }

        /**
         * 交换i位置和j位置上的值
         */
        private void swap(int i, int j) {
            if (i == j)
                return;
            container[i] = container[i] ^ container[j];
            container[j] = container[i] ^ container[j];
            container[i] = container[i] ^ container[j];
        }

        /**
         * 查看堆顶元素
         */
        public int peek() {
            return container[0];
        }
    }
}
相关推荐
爱敲键盘的猴子8 分钟前
深入理解 Java HashMap
java·hashmap
霸道流氓气质9 分钟前
Java开发者AI编程常用MCP、Skills、Rules全景汇总
java·开发语言·ai编程
天涯醉青楼21 分钟前
Spring Boot 接口返回 Bean 时字段名“变形”的深度剖析与解决方案
java
步行cgn38 分钟前
MyBatis 高级映射与延迟加载完全指南
java·tomcat·mybatis
thefool11226638 分钟前
从中序与后序遍历序列构造二叉树
java
吴声子夜歌1 小时前
Java面试题——JVM(二)
java·开发语言·jvm
CRMEB1 小时前
商城大促活动策划全流程:从定目标到复盘四阶段
java·开发语言·人工智能·ai·开源·php
denglinqings1 小时前
Java开发从入门到精通所有课程
java·开发语言
地平线开发者1 小时前
征程6|YOLOv5x 在 Horizon 征程6 上的端到端部署实践(下)
算法·自动驾驶
星空1 小时前
maven镜像
java·maven