首页 > 其他分享 >【LeetCode】215.数组中的第K个最大元素

【LeetCode】215.数组中的第K个最大元素

时间:2024-06-20 17:53:39浏览次数:23  
标签:215 nums int right heapSize 数组 largest LeetCode left

题目描述

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

解法一:快速选择

类似与快速排序,随机选择一个基准pivot,将小于pivot的元素全放在左边,大于pivot的元素全放在右边,并返回pivot所在位置index。每进行一次选择就会确定一个元素的位置,index==n-k表明nums[index]就是第k大元素。如果index<n-k,则在index+1right区间继续选择;index>n-k,则在leftindex-1区间继续选择.

import java.util.Random;


class Solution {
    private final static Random RANDOM = new Random();
    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        int target = len - k;
        int left = 0;
        int right = len - 1;
        while(true){
            int pivotIndex = partition(nums, left, right);
            if(pivotIndex == target){
                return nums[pivotIndex];
            }else if(pivotIndex < target){
                left = pivotIndex + 1;
            }else {
                right = pivotIndex - 1;
            }
        }

    }

    private int partition(int[] nums, int left, int right) {
        //随机选取pivot
        int random = RANDOM.nextInt(right - left + 1);
        swap(nums, left, left+random);
        int pivot = nums[left];
        int le = left + 1;
        int ge = right;
        while(true){
            while(le<=ge && nums[le]<pivot){
                le++;
            }
            while(le<=ge && nums[ge]>pivot){
                ge--;
            }
            if(le>=ge){
                break;
            }
            swap(nums,le, ge);
            le++;
            ge--;
        }
        swap(nums, left, ge);
        return ge;
    }

    private void swap(int[] nums, int left, int random) {
        int temp = nums[left];
        nums[left] = nums[random];
        nums[random] = temp;
    }
}

解法二:堆排序

自己实现最大堆,主要函数:建堆调整删除

  • 时间复杂度:O(nlog⁡n),建堆的时间代价是 O(n),删除的总代价是 O(klog⁡n),因为 k<n,故渐进时间复杂为 O(n+klog⁡n)=O(nlog⁡n)。
  • 空间复杂度:O(log⁡n)O(\log n)O(logn),即递归使用栈空间的空间代价。
class Solution {
    public int findKthLargest(int[] nums, int k) {
        int heapSize = nums.length;
        buildMaxHeap(nums, heapSize);//建堆
        for(int i = 0; i < k; i++){
            swap(nums, 0, heapSize-1);
            heapSize--;
            maxHeapify(nums, 0, heapSize);//调整堆
        }
        return nums[0];
    }

    private void buildMaxHeap(int[] nums, int n) {
        //对所有非叶子节点调整
        for(int i = n/2 - 1; i >= 0; i--){
            maxHeapify(nums, i, n);
        }
    }

    private void maxHeapify(int[] nums, int i, int heapSize) {
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        int largest = i;
        if(left < heapSize && nums[left] > nums[largest]){
            largest = left;
        }
        if(right < heapSize && nums[right] > nums[largest]){
            largest = right;
        }
        if(largest != i){
            swap(nums, largest, i);
            maxHeapify(nums, largest, heapSize);
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

解法三:桶排序

注意到题目提示-10^4 <= nums[i] <= 10^4

把所有相等的元素分别放入一个桶内,从最大元素所在桶依次取出k个元素。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int[] buckets = new int[20001];
        for (int i = 0; i < nums.length; i++) {
            buckets[nums[i] + 10000]++;
        }
        for (int i = 20000; i >= 0; i--) {
            k = k - buckets[i];
            if (k <= 0) {
                return i - 10000;
            }
        }
        return 0;
    }
}

标签:215,nums,int,right,heapSize,数组,largest,LeetCode,left
From: https://www.cnblogs.com/hudad/p/18259182

相关文章

  • 函数内部返回指向字符串的指针和数组名的区别
    目录两道题目进程的内存分布结论两道题目先来看两道与内存管理有关的题目以下程序会出错吗?如果不会则输出什么?#include<stdio.h>char*func(){ char*str="HelloWorld"; returnstr;}intmain(){ char*str=func(); //程序输出HelloWorld printf("%s\n",......
  • LeetCode 热题100 --哈希
    哈希哈希,有限空间映射一个无限的空间。在空间内,有序化进行快速查询。用空间换时间。1.两数之和给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数......
  • java insert数组到postgres数据库
    数组格式在数据库中并不是常用操作,比较常用的是字符串存储后,使用时再进行数据加工.这里记录下直接操作postgresinsert数组的数据操作.表结构CREATETABLEschema.table( report_rowsjsonNULL, series_varcharNULL)实际存在两种数组结构:1字符串数组2json数组.js......
  • NumPy数组操作
    NumPy数组操作1.修改形状arr.reshape(m,n)#将数组修改成m*n的新数组#一维数组importnumpyasnparr=np.arange(10)arr1=arr.reshape(2,5)print("arr:")print(arr)print("arr1:")print(arr1)#二维数组importnumpyasnparr=np.array([[1,2,3,4]......
  • DEMO_02:随机数获取;数组集合遍历;整型与字符串转换;字符串字符遍历;数组/集合排序
    /***考核点:随机数获取;数组集合遍历;整型与字符串转换;字符串字符遍历;数组/集合排序*<p>*题目:*1.使用while循环获取20个五位数随机数并打印;*2.遍历20个数,筛选出随机数中3的倍数,并统计个数;*3.符合2的数中,找出五位数中3的倍数和位置*4.符合2的数中,把这五位数......
  • 数组合并去重排序
     constarr1=[54,67,89,1,4,3,5,0,0,3]    constarr2=[5,5,6,7,8,3,2,5,7,453,54]    functionpopSort(arr){      for(leti=0;i<arr.length;i++){        for(letj=0;j<arr.leng......
  • leetcode 动态规划 (基础版)打家劫舍
    题意:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ......
  • leetcode 动态规划(基础版)删除并获得点数
    题目:给你一个整数数组  ,你可以对它进行一些操作。nums每次操作中,选择任意一个  ,删除它并获得  的点数。之后,你必须删除 所有 等于  和  的元素。nums[i]nums[i]nums[i]-1nums[i]+1开始你拥有 个点数。返回你能通过这些操作获得的最大点数。0题解:要会理解......
  • Vue 中 v-for 的全方位解读:含案例与 key 属性运用及常用数组方法
    目录v-for介绍v-forkey属性的使用Vue数组方法v-for介绍        v-for能够对数字、数组以及对象进行遍历。值得注意的是,当v-for与v-if一同运用时,v-for的优先级要高于v-if。正因如此,应尽量避免将v-if和v-for共同使用。特别是在嵌套使用的情况下,每一......
  • leetcode225用队列实现栈
    本文主要讲解用队列实现栈的要点与细节,按照步骤思考更方便理解,同类型用栈实现队列c++与java代码如下,末尾请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。实现 MyStack 类:voidpush(intx) 将元素x压入栈顶。intp......