[Leetcode 스택 빠른 선택 BFPRT] 배열 요소 K 번째 최대 (215)

이 질문은, 많은 지식을 리드 매우 강력

이름

정렬되지 않은 배열에서 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

참고 :
당신은 항상 유효 케이 가정하고 배열의 1 개 ≤ K ≤ 길이 있습니다.

대답

질문은 쉽게 다음과 같은 솔루션을 생각하게 K 큰 요소의 순서를 찾기 위해 질문 :

1 정렬 시퀀스는 K의 끝에서 두 번째 제거. 빠른 종류의 n은 · 로그 (N)

도 2를 참조하면, 작은 크기의 K 더미 위에 유지 작은 스택의 최상위가 스택의 상단은 K의 스택의 상부 위에 크고, 순차적으로 적층 요소에 서열 요소보다 크다. 힙을 유지 (삽입 O (1), 로그 (N)을 삭제), 총 시간 복잡도가 · 로그 (K) n은 시간 복잡도는 로그 (N), 여기에 로그 (K)이다, 공간의 복잡성 그것은 O (K)이다.

PS : 빅 탑 힙 캔

3, 빠른 선택 알고리즘은 항상 후 빠르게 partation 공정 열, 기준 선택 기준이있다이 경우에, 기준 원점 (기준 시퀀스 미만이 우측보다 크다 그 좌측에 배치된다) 정렬 된 서열 위치는 상기 N 분석보고 재 - 기준 위치가 정확히 k는 동일한 경우, K 소자와 상기 기준 좌표 사이의 관계를 다음 k 번째 K 미만의 좌표 위치를 기준 넘으면 어레이의 개수는 감소함으로써, 기준이며 단지 재귀 왼쪽, 그렇지 않으면 재귀의 오른쪽 절반.

정렬 알고리즘은 빠른 경우가 빠른 정렬 재귀 적 시간 복잡도 · 로그 (n)의 n은 두 부분, 그리고 어디 인해에 N 예측 공지 - 소량 씩 여기서 요소 K, 우리는이 개 부분을 처리 할 필요가 없습니다, 이것은 (n)의 평균 시간 복잡도 O를 감소합니다.

이 알고리즘은 최상의 경우는 각각의 기준 서열이 중간 위치에서 분할되어있다, O (N)의 시간 지원도가 최악의 경우 각각의 기준 에지 위치가 분할되도록하고, 시간 복잡도는 (N ^ 2 O이고 ). 문제를 해결하기 위해 선형 복잡도 O (n)이 시간에, 기준의 선택을 최적화하기위한 네 번째 방법.

4 BFPRT가 BFPRT 알고리즘이 기준의 문제이고, 상기 기준은 상기 어레이의 중간에 각각 위치, 시간 복잡도가 O (N) BFPRT 솔루션 솔루션 신속한 선택 및 유일한 차이라는 기준에 있도록 선택 될 수있다 선택에, 그래서 우리는 참조 과정을 선택에 대해 이야기.

첫 번째 단계 : 우리 배열하는 그룹으로 매 5 개 인접한 숫자, 숫자 5 뒤에 수가 아니라 또한 그룹으로 구분됩니다.

단계 두 : 각 그룹 번호, 우리는 5의 평균 수는 모든 그룹의 중간은 중간 배열 (중간 배열)를 구성하는 것을 찾을 수 있습니다.

세 번째 단계 : 우리가 중간 중간 배열 한 후 평균을 산출 기준을 찾을 수 있습니다.

4 단계 : partation 과정이 참고 문헌으로 같은 종래에 다음 용액을 실시했다.

BFPRT는 TOP-K 문제를 탐색하도록 설계 시간 복잡도는 O (N)이다.

다음과 같이 코드입니다 :

1 정렬

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        return sorted(nums)[-k]

2, 작은 힙의 상단

from heapq import *

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        l = []                               # 存储堆
        for x in nums:
            if l and len(l)==k and x>l[0]:   # 堆满并且x大于堆顶,pop堆顶,x入堆
                heapreplace(l, x)
            if not l or len(l)<k:            # 堆没满,直接入堆
                heappush(l, x)
        return l[0]
        # 或者直接return nlargest(k, nums)[-1]

3, 빠른 선택

import random

class Solution:
    def findKthLargest(self, nums, k):
        def partition(left, right, base):
            temp = nums[base]
            nums[base], nums[right] = nums[right], nums[base]  # 基准和末尾元素互换

            max_index = left
            for i in range(left, right):  # 把所有小于基准的移到左边
                if nums[i] < temp:
                    nums[max_index], nums[i] = nums[i], nums[max_index]
                    max_index += 1

            nums[right], nums[max_index] = nums[max_index], nums[right]  # 基准归位
            return max_index

        def select(left, right, k_smallest):
            """在 nums[left, right] 找第k小的元素"""
            if left == right:  # 递归终止条件
                return nums[left]
            pivot_index = random.randint(left, right)  # 随机选择基准(比固定选第一个要好)
            base_index = partition(left, right, pivot_index)  # 选第一个(left)为基准,并归位。
            if base_index == k_smallest:  # 判断目前已归位的基准,是不是第k_smallest位
                return nums[k_smallest]
            elif k_smallest < base_index:  # go to 左半部分
                return select(left, base_index - 1, k_smallest)
            else:  # go to 右半部分
                return select(base_index + 1, right, k_smallest)

        return select(0, len(nums) - 1, len(nums) - k)  # 第k大,是第n-k小

4 BFPRT

class Solution:
    def findKthLargest(self, nums, k):
        def getmedian(lis):
            """返回序列lis中位数,在BFPRT中就是求每5个数小组的中位数"""
            begin = 0
            end = len(lis)-1

            sum = begin+end
            mid = sum//2 + sum % 2  # 这个地方加上sum%2是为了确保偶数个数时我们求的是中间两个数的后一个
            return sorted(lis)[mid]

        def BFPRT(nums, left, right):
            """分成每5个数一个小组,并求出每个小组内的中位数"""
            num = right-left+1
            offset = 0 if num % 5 == 0 else 1  # 最后如果剩余的数不足5个,我们也将其分成一个小组,和前面同等对待
            groups = num//5 + offset
            median = []  # 中位数数组
            for i in range(groups):
                begin = left+i*5
                end = begin + 4
                Median = getmedian(nums[begin:min(end, right)+1])
                median.append(Median)
            return select(median, 0, groups-1, groups//2)  # 求出生成好的median数组的中位数,作为partation函数的划分值

        def partition(nums, left, right, base):
            """在 nums[left, right] 将基准base归位"""
            temp = nums[base]
            nums[base], nums[right] = nums[right], nums[base]  # 基准和末尾元素互换

            max_index = left
            for i in range(left, right):  # 把所有小于基准的移到左边
                if nums[i] <= temp:  # 要等于啊!这里好坑的说.. 否则通不过[3, 3, 3, 3, 4, 3, 3, 3, 3]  k = 1
                    nums[max_index], nums[i] = nums[i], nums[max_index]
                    max_index += 1
            nums[right], nums[max_index] = nums[max_index], nums[right]  # 基准归位
            return max_index

        def select(nums, left, right, k_smallest):
            """在 nums[left, right] 找第k小的元素"""
            if left == right:  # 递归终止条件
                return nums[left]
            # pivot_index = random.randint(left, right)
            base = BFPRT(nums, left, right)
            base_index = partition(nums, left, right, nums.index(base))  # 选base为基准,并归位。
            if base_index == k_smallest:  # 判断目前已归位的基准,是不是第k_smallest位
                return nums[k_smallest]
            elif k_smallest < base_index:  # 递归左半部分
                return select(nums, left, base_index - 1, k_smallest)
            else:  # 递归右半部分
                return select(nums, base_index + 1, right, k_smallest)
        return select(nums, 0, len(nums) - 1, len(nums) - k)  # 第k大,是第n-k小

PS : 빅 탑 힙 쓸 수와 궁핍은하지 이상한 게시 ..

from heapq import *

class Solution:
    # 用负数入堆建立大顶堆,pop()k次,就是第k大。时间复杂度最坏n·log(n),最好k·log(n),空间复杂度O(n)
    def findKthLargest(self, nums: List[int], k: int) -> int:
        l = []
        for x in nums:
            heappush(l, -x)         # 平均O(1),最坏log(n)
        for x in range(k):
            c = heappop(l)          # log(n)
        return -c

추천

출처www.cnblogs.com/ldy-miss/p/12032321.html