swift算法:数组中的第k个最大元素

1、描述

在未排序的数组中找到第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

 

2、算法

1)、排序

思想:先对数组进行排序,再返回倒数第 k 个元素

func findKthLargest(_ nums : [Int], _ k : Int)->Int{
        /*
         排序,取出第k个元素
         
         */
        var nums = nums.sorted()
        return nums[nums.count-k]
    }

2)快速选择

思想:随机选择一个枢轴。

           使用划分算法将枢轴放在数组中的合适位置 pos。将小于枢轴的元素移到左边,大于等于枢轴的元素移到右边。

           比较 pos 和 N - k 以决定在哪边继续递归处理。

时间复杂度:O(NlogN)。

func findKthLargest(_ nums : [Int], _ k : Int)->Int{
        /*
         快速选择 O(NlogN)。
         随机选择一个枢轴。
         使用划分算法将枢轴放在数组中的合适位置 pos。将小于枢轴的元素移到左边,大于等于枢轴的元素移到右边。
         比较 pos 和 N - k 以决定在哪边继续递归处理。
         */
        var nums = nums
        let size = nums.count
        return quickselect(nums, 0, size-1, size-k)
    }
private func partition(_ nums : inout [Int], _ left : Int, _ right : Int, _ pivot_index : Int)->Int{
        let pivot = nums[pivot_index]
        //将基准元素移到末尾
        nums.swapAt(pivot_index, right)
        var store_index = left
        
        //将左右小于基准的元素移到左边
        for i in left...right{
            if nums[i] < pivot{
                nums.swapAt(store_index, i)
                store_index += 1
            }
        }
        
        //将基准移到最后
        nums.swapAt(store_index, right)
        return store_index
    }
    private func quickselect(_ nums : [Int], _ left : Int, _ right : Int, _ k_smallest :Int)->Int{
        
        var nums = nums
        //返回第k个最小的元素
        //如果只有一个元素
        if left == right{
            return nums[left]
        }
        
        //选择一个随机的基准下标
        var pivot_index = left+Int.randomIntNumber(Range(0...(right-left)))
        pivot_index = partition(&nums, left, right, pivot_index)
        
        //如果第k个最大值等于基准下标
        if k_smallest == pivot_index {
            return nums[k_smallest]
        }else if k_smallest < pivot_index{
            //基准左边查找
            return quickselect(nums, left, pivot_index-1, k_smallest)
        }else{
            //基准右边查找
            return quickselect(nums, pivot_index+1, right, k_smallest)
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值