[Leedcode][第215题][JAVA][数组中的第K个最大元素][快排][优先队列]

【问题描述】[中等]

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。示例 1:输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

【解答思路】

1. 暴力解法(快排)

在这里插入图片描述
时间复杂度:O(NlogN) 空间复杂度:O(1)

import java.util.Arrays;public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;Arrays.sort(nums);return nums[len - k];}
}
2. 借助 partition 操作定位到最终排定以后索引为 len - k 的那个元素(特别注意:随机化切分元素)

在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(1)
在这里插入图片描述

public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;int left = 0;int right = len - 1;// 转换一下,第 k 大元素的索引是 len - kint target = len - k;while (true) {int index = partition(nums, left, right);if (index == target) {return nums[index];} else if (index < target) {left = index + 1;} else {right = index - 1;}}}/*** 在数组 nums 的子区间 [left, right] 执行 partition 操作,返回 nums[left] 排序以后应该在的位置* 在遍历过程中保持循环不变量的语义* 1、[left + 1, j] < nums[left]* 2、(j, i] >= nums[left]** @param nums* @param left* @param right* @return*/public int partition(int[] nums, int left, int right) {int pivot = nums[left];int j = left;for (int i = left + 1; i <= right; i++) {if (nums[i] < pivot) {// 小于 pivot 的元素都被交换到前面j++;swap(nums, j, i);}}// 在之前遍历的过程中,满足 [left + 1, j] < pivot,并且 (j, i] >= pivotswap(nums, j, left);// 交换以后 [left, j - 1] < pivot, nums[j] = pivot, [j + 1, right] >= pivotreturn j;}private void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}

在这里插入图片描述

import java.util.Random;public class Solution {private static Random random = new Random(System.currentTimeMillis());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 index = partition(nums, left, right);if (index < target) {left = index + 1;} else if (index > target) {right = index - 1;} else {return nums[index];}}}// 在区间 [left, right] 这个区间执行 partition 操作private int partition(int[] nums, int left, int right) {// 在区间随机选择一个元素作为标定点if (right > left) {int randomIndex = left + 1 + random.nextInt(right - left);swap(nums, left, randomIndex);}int pivot = nums[left];int j = left;for (int i = left + 1; i <= right; i++) {if (nums[i] < pivot) {j++;swap(nums, j, i);}}swap(nums, left, j);return j;}private void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
} 

在这里插入图片描述

import java.util.Random;public class Solution {private static Random random = new Random(System.currentTimeMillis());public int findKthLargest(int[] nums, int k) {int len = nums.length;int left = 0;int right = len - 1;// 转换一下,第 k 大元素的索引是 len - kint target = len - k;while (true) {int index = partition(nums, left, right);if (index == target) {return nums[index];} else if (index < target) {left = index + 1;} else {right = index - 1;}}}public int partition(int[] nums, int left, int right) {// 在区间随机选择一个元素作为标定点if (right > left) {int randomIndex = left + 1 + random.nextInt(right - left);swap(nums, left, randomIndex);}int pivot = nums[left];// 将等于 pivot 的元素分散到两边// [left, lt) <= pivot// (rt, right] >= pivotint lt = left + 1;int rt = right;while (true) {while (lt <= rt && nums[lt] < pivot) {lt++;}while (lt <= rt && nums[rt] > pivot) {rt--;}if (lt > rt) {break;}swap(nums, lt, rt);lt++;rt--;}swap(nums, left, rt);return rt;}private void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}
3. 优先队列

在这里插入图片描述

import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;// 使用一个含有 len 个元素的最小堆,默认是最小堆,可以不写 lambda 表达式:(a, b) -> a - bPriorityQueue<Integer> minHeap = new PriorityQueue<>(len, (a, b) -> a - b);for (int i = 0; i < len; i++) {minHeap.add(nums[i]);}for (int i = 0; i < len - k; i++) {minHeap.poll();}return minHeap.peek();}
}
import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;// 使用一个含有 len 个元素的最大堆,lambda 表达式应写成:(a, b) -> b - aPriorityQueue<Integer> maxHeap = new PriorityQueue<>(len, (a, b) -> b - a);for (int i = 0; i < len; i++) {maxHeap.add(nums[i]);}for (int i = 0; i < k - 1; i++) {maxHeap.poll();}return maxHeap.peek();}
}

在这里插入图片描述

import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;// 使用一个含有 k 个元素的最小堆PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b);for (int i = 0; i < k; i++) {minHeap.add(nums[i]);}for (int i = k; i < len; i++) {// 看一眼,不拿出,因为有可能没有必要替换Integer topEle = minHeap.peek();// 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去if (nums[i] > topEle) {minHeap.poll();minHeap.add(nums[i]);}}return minHeap.peek();}
}

在这里插入图片描述

import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len = nums.length;// 最小堆PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(k + 1, (a, b) -> (a - b));for (int i = 0; i < k; i++) {priorityQueue.add(nums[i]);}for (int i = k; i < len; i++) {priorityQueue.add(nums[i]);priorityQueue.poll();}return priorityQueue.peek();}
}

在这里插入图片描述

import java.util.PriorityQueue;public class Solution {// 根据 k 的不同,选最大堆和最小堆,目的是让堆中的元素更小// 思路 1:k 要是更靠近 0 的话,此时 k 是一个较大的数,用最大堆// 例如在一个有 6 个元素的数组里找第 5 大的元素// 思路 2:k 要是更靠近 len 的话,用最小堆// 所以分界点就是 k = len - kpublic int findKthLargest(int[] nums, int k) {int len = nums.length;if (k <= len - k) {// System.out.println("使用最小堆");// 特例:k = 1,用容量为 k 的最小堆// 使用一个含有 k 个元素的最小堆PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b);for (int i = 0; i < k; i++) {minHeap.add(nums[i]);}for (int i = k; i < len; i++) {// 看一眼,不拿出,因为有可能没有必要替换Integer topEle = minHeap.peek();// 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去if (nums[i] > topEle) {minHeap.poll();minHeap.add(nums[i]);}}return minHeap.peek();} else {// System.out.println("使用最大堆");assert k > len - k;// 特例:k = 100,用容量为 len - k + 1 的最大堆int capacity = len - k + 1;PriorityQueue<Integer> maxHeap = new PriorityQueue<>(capacity, (a, b) -> b - a);for (int i = 0; i < capacity; i++) {maxHeap.add(nums[i]);}for (int i = capacity; i < len; i++) {// 看一眼,不拿出,因为有可能没有必要替换Integer topEle = maxHeap.peek();// 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去if (nums[i] < topEle) {maxHeap.poll();maxHeap.add(nums[i]);}}return maxHeap.peek();}}
}

【总结】

1.快排核心思想 找partition 随机化可避免极端情况
2.优先队列的使用 最大最小堆
//大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(capacity, (a, b) -> b - a);
//小堆PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.assert 调试使用 程序或软件正式发布后需要关闭

在这里插入图片描述
在这里插入图片描述

转载链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/

参考链接:https://blog.csdn.net/jeikerxiao/article/details/82262487
参考链接:https://www.cnblogs.com/wei-jing/p/10806236.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/425404.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF#420 B. Okabe and Banana Trees 思维|暴力|几何

Okabe needs bananas for one of his experiments for some strange reason. So he decides to go to the forest and cut banana trees. Consider the point (x, y) in the 2D plane such thatx andy are integers and0 ≤ x, y. There is a tree in such a point, and i…

30jquery-qrcode生成二维码

链接&#xff1a;https://pan.baidu.com/s/1KHzX_jFFBaw4QBKBR8UrgA 提取码&#xff1a;qmdo 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 如上所示&#xff0c;建立一个web程序 <% page language"java" contentType"text/html; charsetUTF-…

[剑指offer]面试题第[50]题[JAVA][第一个只出现一次的字符][哈希表][HashMap]

【问题描述】[简单] 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。示例:s "abaccdeff" 返回 "b"s "" 返回 " "【解答思路】 1. 哈希表 时间复杂度&#xff1a;O(N) 空间复…

31.javaweb简介

1 2 3 4 5 6 7javaweb程序简介

[剑指offer]面试题第[38]题[JAVA][字符串的排列][回溯法]

【问题描述】[中等] 输入一个字符串&#xff0c;打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组&#xff0c;但里面不能有重复元素。示例: 输入&#xff1a;s "abc" 输出&#xff1a;["abc","acb","bac",&qu…

32tomcat的目录结构

<% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>歌谣</title> </head> <bod…

[剑指offer]面试题第[52]题[Leedcode][第160题][JAVA][相交链表][双指针]

【问题描述】[简单] 【解答思路】 1. 双指针法 时间复杂度&#xff1a;O(N^2) 空间复杂度&#xff1a;O(1) public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA null || headB null) return null;ListNode pA headA, pB headB;while (pA !…

33tomcat目录结构

1创建一个myhome文件 2创建一个index.jsp文件 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><!DOCTYPE html><html><head><meta charset"utf-8"><title>歌…

复合数据类型,英文词频统计

作业要求&#xff1a;https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2696 1.列表&#xff0c;元组&#xff0c;字典&#xff0c;集合分别如何增删改查及遍历。 列表的增删改查list1 list(this is a list)#增加list1.append(!) #末尾增加元素list1.insert(2,this i…

34tomcat设置默认页面

如何让hah.jsp成为欢迎界面&#xff1f; 在web-inf文件夹中配置项目部署文件web.xml。 添加标签 <welcome-file-list> <welcome-file>/hah.jsp</welcome-file> <welcome-file-list> 改变web.xml文件首页&#xff0c;报 将文件变成hah.jsp 默认页就设置…

[Leetcode][第718题][JAVA][最长重复子数组][动态规划][滑动窗口][暴力]

【问题描述】[中等] 给两个整数数组 A 和 B &#xff0c;返回两个数组中公共的、长度最长的子数组的长度。示例 1:输入: A: [1,2,3,2,1] B: [3,2,1,4,7] 输出: 3 解释: 长度最长的公共子数组是 [3, 2, 1]。 说明:1 < len(A), len(B) < 1000 0 < A[i], B[i] < 100…

[剑指offer]面试题第[53-1]题[JAVA][在排序数组中查找数字-1][二分法][暴力法]

【问题描述】[中等] 统计一个数字在排序数组中出现的次数。 示例 1:输入: nums [5,7,7,8,8,10], target 8 输出: 2 示例 2:输入: nums [5,7,7,8,8,10], target 6 输出: 0【解答思路】 1. 暴力法/遍历 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(1) public int…

[剑指offer]面试题第[53-2]题[JAVA][0-n-1中缺失的数字][二分法][暴力法]

【问题描述】[简单] 一个长度为n-1的递增排序数组中的所有数字都是唯一的&#xff0c;并且每个数字都在范围0&#xff5e;n-1之内。在范围0&#xff5e;n-1内的n个数字中有且只有一个数字不在该数组中&#xff0c;请找出这个数字。示例 1:输入: [0,1,3] 输出: 2 示例 2:输入: …

过拟合问题详解

具体内容来自于读芯术&#xff1a;https://mp.weixin.qq.com/s?__bizMzI2NjkyNDQ3Mw&mid2247487002&idx1&sn05d13bd67a31e38434285c5f0262b95d&chksmea87f6ccddf07fdae17a71819ba0577d099bb49b291093e7c6c7927456febfb3d8d308c30ad6&scene21#wechat_redir…

[Leetcode][第378题][JAVA][有序矩阵中第K小的元素][二分法][归并排序][暴力]

【问题描述】[中等] 给定一个 n x n 矩阵&#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩阵中第 k 小的元素。 请注意&#xff0c;它是排序后的第 k 小元素&#xff0c;而不是第 k 个不同的元素。示例&#xff1a; matrix [[ 1, 5, 9],[10, 11, 13],[12, 13…

设计模式-Builder和Factory模式区别

Builder和Factory模式区别 Builder模式结构&#xff1a; Factory模式一进一出,Builder模式是分步流水线作业。当你需要做一系列有序的工作或者按照一定的逻辑来完成创建一个对象时 Builder就派上用场啦。我们可以看到&#xff0c;Builer模式与工厂模式是极为相似的&#xff0c;…

[剑指offer]面试题第[54]题[JAVA][二叉搜索树的第k大节点][递归][迭代]

【问题描述】[简单] 给定一棵二叉搜索树&#xff0c;请找出其中第k大的节点。示例 1: 输入: root [3,1,4,null,2], k 13/ \1 4\2 输出: 4 示例 2:输入: root [5,3,6,2,4,null,null,1], k 35/ \3 6/ \2 4/1 输出: 4【解答思路】 反向中序遍历 遍历到第k个节点时&…