要查找一个数组中的第 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. 【ssh】SSH连接远程主机的两种方式

    一.基于用户名与密码连接 指令 ssh username@server_ip 随后要求输入密码 加密流程 1️⃣ 在SSH连接建立过程中,客户端和服务器使用Diffie-Hellman密钥交换协议协商 ...

  2. Git插件报错,Appears to be a git repo or submodule

    Hexo博客需要引入第三方插件,不少包作者误把包项目得.git文件上传到github,或者在插件的github路径下直接下载插件文件夹,结果是插件内含有.git文件,导致下载别的npm包时报错npm ...

  3. 【技术积累】JavaScript中的基础语法【一】

    Math对象 JavaScript中的Math对象是一个内置的数学对象,表示对数字进行数学运算的方法和属性的集合. Math对象不是一个构造函数,所以不能使用new关键字来创建一个Math对象的实例. ...

  4. Argument data type text is invalid for argument 1 of replace function

    今天给webapi添加了搜索,结果数据库显示了这个错误, Argument data type text is invalid for argument 1 of replace function 查 ...

  5. Python操纵数据库:peewee

    模块名:peewee 安装方法: pip install peewee 官方教程:http://docs.peewee-orm.com/en/latest/

  6. 在Java中List, Set, Map是否继承自Collection接口?

    List和Set是继承自Collection接口的接口,Set不允许重复的项目,List允许重复项目, Set接口派生的类有TreeSet,HashSet,LinkedHashSet. List接口派 ...

  7. LangChain:打造自己的LLM应用

    1.LangChain是什么 LangChain是一个框架,用于开发由LLM驱动的应用程序.可以简单认为是LLM领域的Spring,以及开源版的ChatGPT插件系统.核心的2个功能为: 1)可以将 ...

  8. 微服务项目使用RabbitMQ

    微服务项目使用RabbitMQ 很久未用RabbitMQ了,根据网上的Demo,大多数是一个服务包含所有的生产者和消费者和配置,当自己去搭建服务的时候,还需要一些思考各种包的划分.无法无脑CV大法,所 ...

  9. PHP秒杀面试题

    什么是秒杀系统:秒杀系统是一个处理大量并发用户请求的系统,通常用于限时促销或特定活动中,用户可以在特定时间内以抢购的方式购买商品或服务. 秒杀系统可能面临的挑战是什么?秒杀系统可能面临以下挑战: 高并 ...

  10. 大怨种的pwn的wp

    0x01 pwnable_echo1 军训几天加暑假的活 from pwn import * context(os='linux', arch='amd64', log_level='debug') ...