要查找一个数组中的第 K 大元素,有多种方法可以实现,其中常用的方法是使用分治算法或快速选择算法,这两种方法的时间复杂度到时候O(n)。

快速选择算法示例:

package main

import "fmt"

func findKthLargest(nums []int, k int) int {
return quickSelect(nums, 0, len(nums)-1, len(nums)-k)
} func quickSelect(nums []int, left, right, k int) int {
if left == right {
return nums[left]
}
pivotIndex := partition(nums, left, right)
if k == pivotIndex {
return nums[k]
} else if k < pivotIndex {
return quickSelect(nums, left, pivotIndex-1, k)
} else {
return quickSelect(nums, pivotIndex+1, right, k)
}
} func partition(nums []int, left, right int) int {
pivot := nums[right]
i := left
for j := left; j < right; j++ {
if nums[j] < pivot {
nums[i], nums[j] = nums[j], nums[i]
i++
}
}
nums[i], nums[right] = nums[right], nums[i]
return i
} func main() {
nums := []int{3, 2, 1, 5, 6, 4}
k := 2
result := findKthLargest(nums, k)
fmt.Printf("The %d-th largest element is: %d\n", k, result)
}

上述代码使用快速选择算法来查找第 K 大的元素,其中 quickSelect 函数递归地在左半部分或右半部分查找,直到找到第 K 大的元素。partition 函数用于对数组进行分区操作,将小于 pivot 值的元素移到左边,大于 pivot 值的元素移到右边。

这种方法的平均时间复杂度为 O(n),其中 n 是数组的长度。最坏情况下的时间复杂度为 O(n^2),但快速选择算法通常在平均情况下表现良好。这个算法是一种不需要额外引入空间消耗的高效查找方法。

注意,也可以考虑使用标准库中的排序函数,然后直接访问第 K 大的元素,但这会引入 O(nlogn) 的排序时间复杂度,因此不如快速选择算法高效。

分治算法示例

使用分治算法查找数组中第 K 大的元素是一种高效的方法,其时间复杂度为 O(n)。下面是使用分治算法实现的查找第 K 大元素的过程:

  1. 分解(Divide):将数组分为若干个子数组,每个子数组包含一组元素。可以使用任何方法来划分数组,例如随机选择一个元素作为枢纽元素(pivot),然后将数组中小于枢纽元素的元素放在左侧,大于枢纽元素的元素放在右侧。这个过程类似于快速排序中的分区操作。

  2. 选择子数组(Select Subarray):根据分解步骤中得到的子数组和枢纽元素的位置,确定要继续查找的子数组。如果 K 大元素的位置在枢纽元素的右侧,那么在右侧的子数组中继续查找;如果在左侧,那么在左侧的子数组中查找。

  3. 递归(Recursion):递归地在所选子数组中查找第 K 大元素。这个过程会反复进行,直到找到第 K 大元素或确定它在左侧或右侧的子数组中。

  4. 合并(Combine):合并步骤通常不需要执行,因为在递归的过程中,只需继续查找左侧或右侧的子数组中的第 K 大元素。

  5. 基本情况(Base Case):递归的终止条件通常是当子数组只包含一个元素时,即找到了第 K 大元素。

下面是一个示例的 Go 代码,实现了查找数组中第 K 大元素的分治算法:

package main

import "fmt"

func findKthLargest(nums []int, k int) int {
if len(nums) == 1 {
return nums[0]
} pivotIndex := partition(nums)
rank := pivotIndex + 1 if rank == k {
return nums[pivotIndex]
} else if rank > k {
return findKthLargest(nums[:pivotIndex], k)
} else {
return findKthLargest(nums[pivotIndex+1:], k-rank)
}
} func partition(nums []int) int {
pivotIndex := len(nums) - 1
pivot := nums[pivotIndex]
i := 0 for j := 0; j < pivotIndex; j++ {
if nums[j] > pivot {
nums[i], nums[j] = nums[j], nums[i]
i++
}
} nums[i], nums[pivotIndex] = nums[pivotIndex], nums[i]
return i
} func main() {
arr := []int{3, 2, 1, 5, 6, 4}
k := 2
result := findKthLargest(arr, k)
fmt.Printf("The %d-th largest element is: %d\n", k, result)
}

这个示例中,findKthLargest 函数使用了分治算法,通过递归地在子数组中查找第 K 大元素,直到找到或确定其在左侧或右侧的子数组中。partition 函数用于将数组分为左侧大于枢纽元素和右侧小于枢纽元素的两部分。

这个算法的时间复杂度是 O(n),其中 n 是数组的长度。这是因为在每次递归中,都会将数组一分为二,从而快速缩小问题规模。这使得分治算法成为一种高效的查找第 K 大元素的方法。

冒泡排序示例

冒泡排序是一种排序算法,通常不是用来查找第 K 大的元素的最佳选择,因为它的时间复杂度较高。然而,你可以结合冒泡排序的思想来查找数组中第 K 大的元素。具体方法是对数组进行 K 次冒泡排序,每次冒泡排序将当前最大的元素移动到数组的末尾,然后查找第 K 大的元素。下面是一个示例实现:

package main

import "fmt"

func findKthLargest(nums []int, k int) int {
if k < 1 || k > len(nums) {
return -1 // 无效的 K
} for i := 0; i < k; i++ {
for j := 0; j < len(nums)-i-1; j++ {
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1], nums[j] // 冒泡排序
}
}
} // 第 K 大的元素位于数组倒数第 K 个位置
return nums[len(nums)-k]
} func main() {
arr := []int{3, 2, 1, 5, 6, 4}
k := 2
result := findKthLargest(arr, k)
fmt.Printf("The %d-th largest element is: %d\n", k, result)
}

在上述示例中,findKthLargest 函数执行 K 次冒泡排序,每次将当前最大的元素冒泡到数组的末尾。最后,第 K 大的元素位于数组倒数第 K 个位置。这个算法的时间复杂度是 O(K*n),其中 n 是数组的长度。虽然不是最高效的算法,但对于小 K 值或小数组来说,是可行的方法。如果 K 较大或数组很大,建议使用其他更高效的算法。


声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意


查找数组中第K大的元素的更多相关文章

  1. 查找数组中第k大的数

    问题:  查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...

  2. [leetcode]215. Kth Largest Element in an Array 数组中第k大的元素

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  3. [经典算法题]寻找数组中第K大的数的方法总结

    [经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26   字体:[大 中 小] 打印复制链接我要评论   今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...

  4. 前端算法题:找出数组中第k大的数字出现多少次

    题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...

  5. LeetCode703 流中第k大的元素

    前言: 我们已经介绍了二叉搜索树的相关特性,以及如何在二叉搜索树中实现一些基本操作,比如搜索.插入和删除.熟悉了这些基本概念之后,相信你已经能够成功运用它们来解决二叉搜索树问题. 二叉搜索树的有优点是 ...

  6. 【每日一题】【找到位置返回&升序数组中第K大就是n-K小】2022年1月17日-NC88 寻找第K大

    描述有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数. 给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在. 方法 ...

  7. [LeetCode] Kth Largest Element in an Array 数组中第k大的数字

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  8. [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的数字

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  9. TopK问题,数组中第K大(小)个元素问题总结

    问题描述: 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 面试中常考的问题之一,同时这道题由于解法众多,也是考察时间复杂 ...

  10. 寻找数组中第K大的数

    给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...

随机推荐

  1. @Import :Spring Bean模块装配的艺术

    本文分享自华为云社区<Spring高手之路8--Spring Bean模块装配的艺术:@Import详解>,作者: 砖业洋__. 本文将带你深入探索Spring框架的装配机制,以及它如何使 ...

  2. Python开发者必读:Pip使用全攻略与最佳实践

    在这篇文章中,我们将深入探讨Python的主要包管理工具--Pip.内容涵盖了Pip的基本概念.安装和配置.中国国内镜像源的使用.包管理.与虚拟环境的关系.高级用法.问题解决. 1. 引言 在现代的软 ...

  3. 2023-07-23:给你 n 个任务和 m 个工人 每个任务需要一定的力量值才能完成 需要的力量值保存在下标从 0 开始的整数数组 tasks 中 第 i 个任务需要 tasks[i] 的力量才能完

    2023-07-23:给你 n 个任务和 m 个工人 每个任务需要一定的力量值才能完成 需要的力量值保存在下标从 0 开始的整数数组 tasks 中 第 i 个任务需要 tasks[i] 的力量才能完 ...

  4. Python和PyTorch深入实现线性回归模型:一篇文章全面掌握基础机器学习技术

    1. 简介 1.1 线性回归模型概述 线性回归是一种统计学中的预测分析,该方法用于建立两种或两种以上变量间的关系模型.线性回归使用最佳的拟合直线(也称为回归线)在独立(输入)变量和因变量(输出)之间建 ...

  5. Django创建超级管理员用户

    python manage.py createsuperuser 后面就会提示你输入用户名.邮箱以及密码.

  6. FreeSWITCH通过mod_mariadb原生连接MySQL

    前言 根据官方更新说明(https://freeswitch.org/confluence/display/FREESWITCH/FreeSWITCH+1.10.x+Release+notes),从1 ...

  7. vue实现文本复制

    一. 下载插件 npm install --save vue-clipboard2 二. main.js import VueClipBoard from 'vue-clipboard2' Vue.u ...

  8. IOS App内嵌H5 swiper 轮播出现卡顿白屏闪烁

    话说在前头:前端开发同学遇到这个问题不慌,因为接下来你要踩的坑我都帮你们踩完了,所以有了这一篇博客.希望能帮到你 轮播组件:swiper@4.5.1 (4x稳定的最后一个版本) 设备:ios版本15x ...

  9. 论文解读(BSFDA)《Black-box Source-free Domain Adaptation via Two-stage Knowledge Distillation》

    Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Black-box Source-free Domain Adaptation via Two-stage ...

  10. 《Kali渗透基础》04. 主动信息收集(一)

    @ 目录 1:主动信息收集 2:发现 3:二层发现 3.1:arping 3.2:nmap 3.3:netdiscover 3.4:Scapy 4:三层发现 4.1:ping 4.2:Scapy 4. ...