k-th smallest/biggest 问题大约有这几道:

373. Find K Pairs with Smallest Sums 从两个list里各取一个数求和,求所有可能的sum里第k小的
378. Kth Smallest Element in a Sorted Matrix 给一个每一横排/每一纵列都有序的matrix,求其中第k小的元素
668. Kth Smallest Number in Multiplication Table 给一个乘法表(类似378的matrix),求其中第k小的元素
719. Find K-th Smallest Pair Distance 从一个list里取两个元素求和,求所有可能的sum里第k小的
786. K-th Smallest Prime Fraction 从一个list里取两个元素相除,求所有可能的sum里第k小的

可以看出,其实373 719 786是同一题,378 668是同一题

这种题大致有两种思路:

1. 用heap

关于堆的介绍网上有一大把......这里只划重点

堆是一种是一种特殊的完全二叉树,其中每个根节点一定比它的左、右儿子节点都大/小(大根堆or小根堆)。每次增/删元素时,需要移动二叉树节点来保持这一性质。

时间复杂度:

从一个长度为N的乱序数组建堆  O(NlogN)

向长度为N的堆插入/删除一个元素  O(logN)

实现:

C++里可以用priority_queue<int> pq。常用操作有push(), pop(), top(), empty(), size()

Python 里可以用import heapq,然后heapq.heapify(list_a)就在原list上建好堆啦,a[0]就是堆顶。不过它只能建大根堆

 import heapq

 #heapq implemented min heap only. Thus we save -nums[i] into the heap
class Solution:
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
a=[]
res=[]
for i in range(len(nums)):
a.append(-nums[i])
if(i>=k):
a.remove(-nums[i-k])
heapq.heapify(a)
if(i>=k-1):
res.append(-a[0])
return res sl=Solution()
nn=[1,3,-1,-3,5,3,6,7]
rr=sl.maxSlidingWindow(nn,3)
print(rr)

Python的implementation实例(LeetCode 239的弱鸡解法)

解题思路:

把所有要比较的东西都塞到heap里,最后做k次取堆顶--弹出堆顶的操作

时间复杂度是 O(N^2 * log(N^2)) 有些medium题能过,但hard题肯定不行

根据题目具体情况,一开始不一定所有的东西都要塞进heap

例题:

373. Find K Pairs with Smallest Sums

反正过是能过...它的加强版就是719 786啦

priority_queue默认是大根堆,要是想要小根堆需要自定义比较函数。这里我直接重载了运算符(因为是pair嘛),推荐一下这种写法(骄傲

 class Solution {
public:
struct Node
{
pair<int, int> val;
Node(int x,int y) {val=pair<int, int>(x,y);}
bool operator <(Node a) const {return(val.first+val.second < a.val.first+a.val.second);}
bool operator >(Node a) const {return(val.first+val.second > a.val.first+a.val.second);}
}; vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k)
{
vector< pair<int, int> > ans;
int lx=nums1.size(),ly=nums2.size();
if(lx== || ly==) return ans;
k=min(k,lx*ly);
priority_queue<Node, vector<Node>, greater<Node> > pq;
for(int i=;i<min(lx,k);i++)
for(int j=;j<min(ly,k);j++)
{
pq.push(Node(nums1[i], nums2[j]));
} while(k)
{
ans.push_back(pq.top().val);
pq.pop();
k--;
}
return ans; }
};

378. Kth Smallest Element in a Sorted Matrix

赤果果的heap。又不是不能用......

 //O(N*N*log(N*N))
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k)
{
int dx=matrix.size(),dy=matrix[].size();
priority_queue<int> pq;
for(int i=;i<dx;i++)
for(int j=;j<dy;j++)
pq.push(matrix[i][j]); int ans;
k=dx*dy-k+;
while(k)
{
ans=pq.top();
pq.pop();
k--;
}
return ans;
}
};

另外三题heap都是妥妥超时的噢......hard就是hard

2. Binary Search

二分查找模板了解一下:

under_construction

时间复杂度:

O(log(N))

解题思路:

用二分查找(有left, right, mid)来枚举第k小的值,然后看原数组里当前有多少是小于mid的,多了就减小right,少了就增大left。直到查找结束,此时left就是第k小值啦

实现时先对原数组按行/列排个序,或者题目本身就是保证有序的

时间复杂度是 O(log(X)*N) ,其中log(X)是二分查找的开销(X=right-left),N是在原数组里找小于mid的数的开销(二维数组的话最坏情况可能会N^2,不过一般也能过)

例题:

378. Kth Smallest Element in a Sorted Matrix

就按上面的方法实现哒

在原数组里count时用了一个函数upper_bound(matrix[i].begin(), matrix[i].end(), mid),返回matrix[i]这个从小到大有序的vector里小于等于mid的第一个数的指针

这玩意底层是二分查找,时间复杂度是logN呢。

 //O(N*log(N)*log(max-min))
//Binary Search
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k)
{
int dx=matrix.size(),dy=matrix[].size();
int ml=matrix[][], mr=matrix[dx-][dy-];
int mid,cnt;
while(ml<mr)
{
mid=(ml+mr)/;
cnt=;
for(int i=;i<dx;i++)
{
cnt+=upper_bound(matrix[i].begin(), matrix[i].end(), mid)-matrix[i].begin();
}
if(cnt>=k)
mr=mid;
else if(cnt<k)
ml=mid+;
}
return ml;
}
};

668. Kth Smallest Number in Multiplication Table

上面的改巴改巴就行了......

 //Binary Search
class Solution {
public:
//int kthSmallest(vector<vector<int>>& matrix, int k)
int findKthNumber(int m, int n, int k)
{
int ml=, mr=m*n;
int mid,cnt;
while(ml<mr)
{
mid=(ml+mr)/;
cnt=;
for(int i=;i<=m;i++)
{
cnt+=min(mid/i,n);
}
if(cnt>=k)
mr=mid;
else if(cnt<k)
ml=mid+;
}
return ml;
}
};

719. Find K-th Smallest Pair Distance

一样的套路噢...就是从一个matrix变成了两个list

 // Binary Search
class Solution {
public:
int smallestDistancePair(vector<int>& nums, int k)
{
int n=nums.size();
sort(nums.begin(), nums.end());
int ml=nums[]-nums[],mr=nums[n-]-nums[],mid=,cnt=;
for(int i=;i<n-;i++) ml=min(ml,nums[i+]-nums[i]);
while(ml<mr)
{
mid=(ml+mr)/;
cnt=;
for(int i=;i<n;i++)
{
int j=i+;
while(j<n && nums[j]-nums[i]<=mid) j++;
cnt+=(j-i-);
}
if(cnt<k)
ml=mid+;
else
mr=mid;
}
return ml;
}
};

这题其实还有个骚操作:因为list值的范围比较小,所以可以用counting sort:先用O(N^2)的时间把所有可能的pair和记下来,然后在counting sort的数组里从小到大数数即可

不过感觉这方法通用性应该不强...

 //counting sort: O(N^2)
class Solution {
public:
int smallestDistancePair(vector<int>& nums, int k)
{
int val[];
memset(val,,sizeof(val));
int nl=nums.size();
for(int i=;i<nl;i++)
for(int j=i+;j<nl;j++)
{
//cout<<abs(nums[j]-nums[i])<<endl;
val[abs(nums[j]-nums[i])]++;
} int ans=;
while(k)
{
if(val[ans]>)
{
//cout<<k<<" "<<ans<<endl;
val[ans]--;
k--;
}
else ans++;
}
return ans;
}
};

786. K-th Smallest Prime Fraction

这题坑多一点,因为是分数,涉及到浮点数嘛

涉及到浮点数就不能直接用=比较辣,要用r-l<eps。

以及注意两个int做除法,要先强制转换成double

 //Binary Search, AC
class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int k)
{
vector<int> ans;
int al=A.size();
sort(A.begin(), A.end());
double ml=0.0, mr=1.0, md=0.5;
int dx,dy,cnt;
double eps=1e-;
while(mr-ml>eps)
{
md=(ml+mr)/;
cnt=;
for(int i=;i<al;i++)
{
int j=al-;
while(j>i && (double)A[i]/(double)A[j]<md) j--;
cnt+=(al--j);
}
cout<<ml<<","<<mr<<"=="<<md<<" "<<cnt<<endl;
if(cnt<k)
ml=md;
else
mr=md; }
for(int i=;i<al;i++)
for(int j=i+;j<al;j++)
if(abs((double)A[i]/(double)A[j] - ml)<eps)
{
dx=A[i]; dy=A[j];
ans.push_back(dx); ans.push_back(dy);
return(ans);
}
return ans;
}
};

k-th smallest 问题总结的更多相关文章

  1. [Swift]LeetCode786. 第 K 个最小的素数分数 | K-th Smallest Prime Fraction

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  2. [LeetCode] K-th Smallest Prime Fraction 第K小的质分数

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  3. [Algorithm] How to use Max Heap to maintain K smallest items

    Let's say we are given an array: [,,,,,,] We want to get K = 3 smallest items from the array and usi ...

  4. [LeetCode] 786. K-th Smallest Prime Fraction 第K小的质分数

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  5. Find the largest K numbers from array (找出数组中最大的K个值)

    Recently i was doing some study on algorithms. A classic problem is to find the K largest(smallest) ...

  6. 【转载】两个排序数组的中位数 / 第K大元素(Median of Two Sorted Arrays)

    转自 http://blog.csdn.net/zxzxy1988/article/details/8587244 给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素.另外一种更加具 ...

  7. 算法打基础——顺序统计(找第k小数)

    这次主要是讲如何在线性时间下找n个元素的未排序序列中第k小的数.当然如果\(k=1 or k=n\),即找最大最小 数,线性时间内遍历即可完成,当拓展到一般,如中位数时,相关算法就值得研究了.这里还要 ...

  8. HDU - 6041:I Curse Myself(Tarjan求环&K路归并)

    There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...

  9. 786. K-th Smallest Prime Fraction

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  10. LeetCode 4 Median of Two Sorted Arrays (两个数组的mid值)

    题目来源:https://leetcode.com/problems/median-of-two-sorted-arrays/ There are two sorted arrays nums1 an ...

随机推荐

  1. IDEA2016 maven项目配置Junit

    添加插件:File->Settings->Plugins 设置生成模式:File->Settings->Other Settings 修改模板:File->Setting ...

  2. MAC地址表、ARP缓存表以及路由表

    一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据 ...

  3. Vue2.0学习笔记

    环境搭建 vue-cli@3    vue-cli@2.X npm i -g @vue/cli 模板语法 文本 <span>Message: {{ msg }}</span> ...

  4. Android 梯形进度条、下载进度条;

    额,Gif有点卡: 梯形.矩形.圆角.背景色.前景色.进度条中的文字都可以改: <?xml version="1.0" encoding="utf-8"? ...

  5. xsyProblem A: 密集子图(graph)

    f[i][S]三进制压缩表示最长路为i,0代表不在该集合,1代表不是最短路为i集合,2代表是最短路集合, 转移枚举i+1集合是那些, 乘以概率即可 预处理保证复杂度 #include<cstdi ...

  6. 批量移动AD用户到指定OU

    原文链接:http://blog.51cto.com/shubao/1346469 作为域管理员,在日常工作中使用ADUC(AD用户和计算机)工具在图形界面中进行账号管理操作可谓是家常便饭了.然而一个 ...

  7. jschDemo

    jsch是java的sftp实现 import com.jcraft.jsch.*; import java.io.OutputStream; public class JschStart { pub ...

  8. type的解释

    在jquery-19.1.1源码中,type,检查对象的类型是:Boolean/Number/String/Function/Array/Date/RegExp/Object/Error中的一种,返回 ...

  9. Python设计模式 - UML - 组件图(Component Diagram)

    简介 组件图又称构建图,用于显示系统各组件及各组件关系的物理视图. 组件图通常包括组件.接口.关系.端口和连接器,用来显示程序代码中相应的模块.源文件或源文件集合之间的依赖和泛化关系. 组件图中的组件 ...

  10. hdu 4714 树+DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714 本来想直接求树的直径,再得出答案,后来发现是错的. 思路:任选一个点进行DFS,对于一棵以点u为 ...