【Leetcode 堆、快速选择、Top-K问题 BFPRT】有序矩阵中第K小的元素(378)
题目
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
说明:
你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n2 。
解答
这个问题和Leetcode 215笔记非常相似,可以用相同的几种思路解决掉。其中BFPRT时间复杂度O(N)
但这个题的输入是一个有序的矩阵,应该是有更好的办法吧!?找一圈没找到,有时间再来看。
思路:
1,全部收入列表,排序,取值。O(N·log(N))
2,维护一个大小为 k 的堆,元素大于等于堆顶负数入堆,堆顶就是第k小。O(N·log(k))
3,快速选择。最好O(N),最坏O(N^2)
4,BFPRT。O(N)
注:N表示元素个数,即n^2个
通过代码如下:
import random
from heapq import *
class Solution:
# 排序
# def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
# l = []
# for m in matrix:
# l.extend(m)
# return sorted(l)[k-1]
# 快速选择
# def kthSmallest(self, matrix, k):
# nums = []
# for m in matrix:
# nums.extend(m)
# 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, k-1) # 第k大,是第n-k小
# 堆
# def kthSmallest(self, matrix, k):
# nums = []
# for m in matrix:
# nums.extend(m)
# hq = []
# for x in nums:
# if len(hq) < k:
# heappush(hq, -x)
# elif -x >= hq[0]:
# heapreplace(hq, -x)
# return -heappop(hq)
# BFPRT
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
nums = []
for m in matrix:
nums.extend(m)
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 getmedian(median)
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, k-1) # 第k大,是第n-k小
【Leetcode 堆、快速选择、Top-K问题 BFPRT】有序矩阵中第K小的元素(378)的更多相关文章
- [LeetCode] Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- [LeetCode] 378. Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- LeetCode 378. 有序矩阵中第K小的元素(Kth Smallest Element in a Sorted Matrix) 13
378. 有序矩阵中第K小的元素 378. Kth Smallest Element in a Sorted Matrix 题目描述 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩 ...
- Leetcode 378.有序矩阵中第k小的元素
有序矩阵中第k小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, ...
- Java实现 LeetCode 378 有序矩阵中第K小的元素
378. 有序矩阵中第K小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ ...
- 有序矩阵中第k小元素
有序矩阵中第k小元素 题目: 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素. 请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素. 看到有序就会想 ...
- leetcode.矩阵.378有序矩阵中第K小的元素-Java
1. 具体题目 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, 5, ...
- 378 Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素.示例:matrix = [ [ 1, 5, 9], [ ...
- 【力扣】有序矩阵中第K小的元素
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素.请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素. 示例: matrix = [ [ 1, 5, ...
随机推荐
- BZOJ 2683: 简单题(CDQ 分治)
题面 Time Limit: 50 Sec Memory Limit: 128 MB Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: ...
- Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?
up vote57down votefavorite 19 I just noticed the iOS 6/7 Delta property found under the UIView's str ...
- dubbo入门学习(三)-----dubbo整合springboot
springboot节省了大量的精力去配置各种bean,因此通过一个简单的demo来整合springboot与dubbo 一.创建boot-user-service-provider 本篇博文基于上篇 ...
- ArrayList基础知识
ArrayList简介 ArrayList 的底层是数组队列,相当于动态数组.与 Java 中的数组相比,它的容量能动态增长.在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ...
- 适配器模式(Adapter\Adaptee)
将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. (1)目标(Target)——客户所期待得到的接口,目标可以是具体的或抽象的类,也可以是接 ...
- docker 安装redis 并配置外网可以访问 - flymoringbird的博客 - CSDN博客
原文:docker 安装redis 并配置外网可以访问 - flymoringbird的博客 - CSDN博客 端口映射,data目录映射,配置文件映射(在当前目录下进行启动). docker run ...
- struts2-自定义拦截器-struts2标签
1 自定义拦截器 1.1 架构 1.2 拦截器创建 创建方式1 创建方式2 创建方式3 ★★★★ 1.3 拦截器api 放行 前后处理 不放行,直接跳转到一个结果页面 不执行后续的拦截器以及Actio ...
- java随机生成字符串工具类
package aA; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; /** * 字符随机 ...
- groups 用户所归属的用户组查询
groups 用法很简单,就是查询用户所归属哪个或哪些用户组: 语法格式: groups 用户名 实例: [beinan@localhost ~]$ groups beinan 注:查询bein ...
- Leetcode438.Find All Anagrams in a String找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100. 说明: ...