IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 力扣215:数组中的第K个最大元素(Java快速查找、计数排序、堆排序) -> 正文阅读

[数据结构与算法]力扣215:数组中的第K个最大元素(Java快速查找、计数排序、堆排序)

一、题目描述

给定整数数组 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
?

提示:

1 <= k <= nums.length <= 105
-104?<= nums[i] <= 104

二、思路讲解

? ? ? ? 2.1 方法一:暴力

? ? ? ? 首先很容易想到将数组排序,然后找到第k大的数字。

public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }

? ? ? ? 时间复杂度:? ? ? ? O(NlogN)

? ? ? ? 空间复杂度:? ? ? ? O(1)?

? ? ? ? 虽然可以通过,但是快速排序的时间复杂度达到了NlogN。我们还需要降低时间复杂度。

? ? ? ? 2.2 方法二:快速选择?

? ? ? ? 根据快速排序的知识我们可以知道,每次partition算法会将所选的基准数(记为target)放到正确的位置,而我们其实只需要知道第k大的位置上的数是什么,而不需要关心其他位置是否有序。那么我们可以根据基准数的位置来判断,假如k在target的左边,那么我们只需要递归target左边即可,而不需要关心target右边是否有序;反之,如果k在target右边,我们只需要递归右边。

class Solution {
    
    public int findKthLargest(int[] nums, int k) {
        return quickSelect(nums, 0, nums.length-1, nums.length-k);
    }

    /**
        partition算法
     */
    int partition(int []nums, int i, int j) {
        int target = nums[i];
        while(i<j) {
            while(i<j && nums[j]>=target) {
                j--;
            }
            nums[i] = nums[j];
            while(i<j && nums[i]<=target) {
                i++;
            }
            nums[j] = nums[i];
        }
        nums[i] = target;
        return i;
    }

    /**
        快速选择算法
     */
    int quickSelect(int []nums, int i, int j, int index) {
        if(i>=j) {
            return nums[i];
        }
        int k = partition(nums, i, j);
        if(k == index) {
            return nums[k];
        } else if(k < index) {
            //只递归右半边
            return quickSelect(nums, k+1, j, index);
        } else {
            //只递归左半边
            return quickSelect(nums, i, k-1, index);
        }
    }
}

? ? ? ? 时间复杂度:? ? ? ? O(N)

? ? ? ? 空间复杂度:? ? ? ? O(logN)????????递归使用栈空间的空间代价的期望为 O(logn)?

? ? ? ? 2.3 方法三:堆排序?

? ? ? ? 了解堆排序的朋友们应该可以想到,构建一次大顶堆,堆顶元素就是数组中最大的数,构建第二次大顶堆,堆顶元素就是第二大的数……那么,我们构建k次大顶堆,堆顶元素就是第k大的数了。

class Solution {
    
    public int findKthLargest(int[] nums, int k) {        
        return heapSort(nums, k);
    }

    int heapSort(int []nums, int k) {
        for (int i = nums.length/2-1; i >= 0; i--) {
            adjustHeap(nums, i, nums.length);
        }

        //操作k-1次,即可找到第k大的元素
        for (int i=nums.length-1; i>nums.length-k-1; i--) {
            int temp = nums[i];
            nums[i] = nums[0];
            nums[0] = temp;
            adjustHeap(nums, 0, i);
        }
        return nums[nums.length-k];
    }

    void adjustHeap(int []nums, int i, int length) {
        int temp = nums[i];
        for (int k=2*i+1; k<length; k=2*k+1) {
            if ((k+1)<length && nums[k]<nums[k+1]) {
                k++;
            }
            if (nums[k]>temp) { 
                nums[i] = nums[k];   
                i = k;  
            } else {
                break;  
            }
        }
        nums[i] = temp;
    }
}

? ? ? ? 2.4 方法四:计数排序

? ? ? ? 题目中只要求时间,没有要求空间,且数字的范围不算很大,那就很适合计数排序了。思想很简单,就不过多介绍了。

class Solution {
    
    public int findKthLargest(int[] nums, int k) {
        
        //考虑负数
        int []count = new int[20001];
        for(int num : nums) {
            count[num+10000]++;
        }
        
        for(int i=count.length-1; i>=0; i--) {
            k -= count[i];
            if(k<=0) {
                return i-10000;
            }
        }
        return -1;
    }
}

? ? ? ? 时间复杂度:? ? ? ? O(N)

? ? ? ? 空间复杂度:? ? ? ? O(N)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 21:07:03  更:2022-10-08 21:08:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:47:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码