数组算法之【数组中第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];
        }
    }
}
相关推荐
CoderYanger5 小时前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第二弹)
java·数据库·spring boot·spring·面试·java-ee·mybatis
CQU_JIAKE7 小时前
11.7[高体】
java·后端·spring
apcipot_rain8 小时前
C++转Java日记(04)
java·开发语言·c++
NEFU_Jyj8 小时前
牛客周赛R168
算法
特立独行的猫A9 小时前
我给女儿写了个打字练习:一边敲键盘,一边把小学英语单词记牢
java·后端·python
憧憬成为java架构高手的小白10 小时前
LangGraph4j 实战(下)
java
天诰10 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
这个昵称不容易14 小时前
SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在
java·springboot·毕设
计算机毕设定制辅导-无忧学长14 小时前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统
likexuec15 小时前
数据结构(2)
数据结构