由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - 关于找最大半径K子集的DP题的总结(更新非DP算法)
相关主题
Young table的搜索最快能到多少阿?问个不常见的排列组合题(或者集合子集问题)
复杂度讨论一下careercup上的一道题,找周边全是1的最大子方阵
请教一道题没人上题,我来上一道吧
onsite回来刚刚被Google电面了,真失败
G家电面题目an interview question
请教一道算法题一个题
两个Sorted Array,找K smallest element求教移除数组重复元素的时间复杂度!!
关于求the kth smallest in two sorted array谷歌电面回馈
相关话题的讨论汇总
话题: dp话题: count话题: int话题: 复杂度话题: 元素
进入JobHunting版参与讨论
1 (共1页)
A*********r
发帖数: 564
1
受到大虾的指点,本题除了DP算法,还有非DP的简单算法, 我的理解如下:
思路就是利用给定的数组范围确定pair distance的最大值和最小值,在这个范围里寻找一个最大的半径X,使得这个半径有K个元素两两距离不小于X;但所有比这个半径大的数,都只有少于K个元素的子集。
这个的算法复杂度是O(MN), 如果还要继续优化的话,就是在查找X的时候用上binary search, 把算法复杂度降为O(MlogN)。(当然前提也是要sort数组先O(M*logM)或者O(M))。
min=0;
max=N;
while(min {
x=(min+max)/2;
count=1;
prev=a[0];
for(i=1;i {
if(a[i]-prev>=x)
count++;
if(count>=k) break;
}
if(count else min=x;
}
==================================
t****a
发帖数: 1212
2
Well it is pretty good idea for the binary search here.

DP.

【在 A*********r 的大作中提到】
: 受到大虾的指点,本题除了DP算法,还有非DP的简单算法, 我的理解如下:
: 思路就是利用给定的数组范围确定pair distance的最大值和最小值,在这个范围里寻找一个最大的半径X,使得这个半径有K个元素两两距离不小于X;但所有比这个半径大的数,都只有少于K个元素的子集。
: 这个的算法复杂度是O(MN), 如果还要继续优化的话,就是在查找X的时候用上binary search, 把算法复杂度降为O(MlogN)。(当然前提也是要sort数组先O(M*logM)或者O(M))。
: min=0;
: max=N;
: while(min: {
: x=(min+max)/2;
: count=1;
: prev=a[0];

h**k
发帖数: 3368
3
赞一个。最后使用的二分查找实在是太巧妙了。
另外,N是为了直接用二分查找来做这题的。

DP.

【在 A*********r 的大作中提到】
: 受到大虾的指点,本题除了DP算法,还有非DP的简单算法, 我的理解如下:
: 思路就是利用给定的数组范围确定pair distance的最大值和最小值,在这个范围里寻找一个最大的半径X,使得这个半径有K个元素两两距离不小于X;但所有比这个半径大的数,都只有少于K个元素的子集。
: 这个的算法复杂度是O(MN), 如果还要继续优化的话,就是在查找X的时候用上binary search, 把算法复杂度降为O(MlogN)。(当然前提也是要sort数组先O(M*logM)或者O(M))。
: min=0;
: max=N;
: while(min: {
: x=(min+max)/2;
: count=1;
: prev=a[0];

t*******7
发帖数: 108
4
very good!
A*********r
发帖数: 564
5
你的意思是直接用2分查找作,而不用DP?
能简单说一下思路吗?

【在 h**k 的大作中提到】
: 赞一个。最后使用的二分查找实在是太巧妙了。
: 另外,N是为了直接用二分查找来做这题的。
:
: DP.

t****a
发帖数: 1212
6
han6 post his solution on the previous discussion

【在 A*********r 的大作中提到】
: 你的意思是直接用2分查找作,而不用DP?
: 能简单说一下思路吗?

h**k
发帖数: 3368
7
版上有人说过的。因为值域是1-N,所以solution的可能范围是0-N/k。对一个给定的值
x,我们很容易判断是否能找到k个元素,使得他们之间的最小距离大于等于x,这个判
断需要O(M)。注意,如果对于x不能找到这么k个元素,那么对于任何x'>x,都不可能找
到。这就构成了二分查找的判定条件,可以用二分查找找到最大的整数x,使得对于x我
们能发现k个元素。总的时间是O(MlogN)。

【在 A*********r 的大作中提到】
: 你的意思是直接用2分查找作,而不用DP?
: 能简单说一下思路吗?

A*********r
发帖数: 564
8
谢谢,一门心思看dp, 忽略了他的帖子。。

【在 t****a 的大作中提到】
: han6 post his solution on the previous discussion
A*********r
发帖数: 564
9
嗯,谢谢,这个比DP好理解多了,除非出题人故意刁难说N很大,否则这个时间复杂度
肯定比DP好啊。。

【在 h**k 的大作中提到】
: 版上有人说过的。因为值域是1-N,所以solution的可能范围是0-N/k。对一个给定的值
: x,我们很容易判断是否能找到k个元素,使得他们之间的最小距离大于等于x,这个判
: 断需要O(M)。注意,如果对于x不能找到这么k个元素,那么对于任何x'>x,都不可能找
: 到。这就构成了二分查找的判定条件,可以用二分查找找到最大的整数x,使得对于x我
: 们能发现k个元素。总的时间是O(MlogN)。

A*********r
发帖数: 564
10
有一点想不通,如何只用O(M)判断是否能找到K个元素,使得他们之间的最小距离大于
等于给定的X?

【在 h**k 的大作中提到】
: 版上有人说过的。因为值域是1-N,所以solution的可能范围是0-N/k。对一个给定的值
: x,我们很容易判断是否能找到k个元素,使得他们之间的最小距离大于等于x,这个判
: 断需要O(M)。注意,如果对于x不能找到这么k个元素,那么对于任何x'>x,都不可能找
: 到。这就构成了二分查找的判定条件,可以用二分查找找到最大的整数x,使得对于x我
: 们能发现k个元素。总的时间是O(MlogN)。

相关主题
请教一道算法题问个不常见的排列组合题(或者集合子集问题)
两个Sorted Array,找K smallest element讨论一下careercup上的一道题,找周边全是1的最大子方阵
关于求the kth smallest in two sorted array没人上题,我来上一道吧
进入JobHunting版参与讨论
h**k
发帖数: 3368
11
greedy算法。

【在 A*********r 的大作中提到】
: 有一点想不通,如何只用O(M)判断是否能找到K个元素,使得他们之间的最小距离大于
: 等于给定的X?

A*********r
发帖数: 564
12
(根据建议,修改非DP版本如下)
min=0;
max=N;
while(min {
x=(min+max)/2;
count=1;
prev=a[0];
for(i=1;i {
if(a[i]-prev>=x)
count++;
if(count>=k) break;
}
if(count else min=x;
}

【在 h**k 的大作中提到】
: greedy算法。
h**6
发帖数: 4160
13
楼上的代码好像仍然不是很对,这是两个版本的代码,假设a已排序。
由于a排序需要额外的复杂度,因此两个版本的复杂度差别不是很大。
逐个查找,O(M),总复杂度O(MlogM+MlogN)
bool findelements(int* a, int M, int K, int x)
{
int prev = a[0];
int count = 1;
for(int i=1; i {
if(a[i] >= prev+x)
{
count++;
prev = a[i];
}
}
return count>=K;
}
二分查找,O(KlogM),总复杂度O(MlogM+KlogMlogN)
bool findelements(int* a, int M, int K, int x)
{
int* prev = a;
for(int i=1; i {
int* curr = lower
h**k
发帖数: 3368
14
你这个程序是直接用二分法找到最大的x么?
如果是的话,中间for循环里找k个元素满足最小距离大于x的代码,好像不对。
应该是
int count = 1;
int pre_ele = a[0];
for( int i=1; i {
if( a[i] - pre_ele >= x )
{
count++;
pre_ele = a[i];
}
}

【在 A*********r 的大作中提到】
: (根据建议,修改非DP版本如下)
: min=0;
: max=N;
: while(min: {
: x=(min+max)/2;
: count=1;
: prev=a[0];
: for(i=1;i: {

s*****v
发帖数: 360
15
不赞不行

寻找一个最大的半径X,使得这个半径至少有K-1个pair distance;但所有比这个半径
大的数,都只有少于K-1个pair distance。
search, 把算法复杂度降为O(MlogN)。(当然前提也是要sort数组先)。

【在 A*********r 的大作中提到】
: 受到大虾的指点,本题除了DP算法,还有非DP的简单算法, 我的理解如下:
: 思路就是利用给定的数组范围确定pair distance的最大值和最小值,在这个范围里寻找一个最大的半径X,使得这个半径有K个元素两两距离不小于X;但所有比这个半径大的数,都只有少于K个元素的子集。
: 这个的算法复杂度是O(MN), 如果还要继续优化的话,就是在查找X的时候用上binary search, 把算法复杂度降为O(MlogN)。(当然前提也是要sort数组先O(M*logM)或者O(M))。
: min=0;
: max=N;
: while(min: {
: x=(min+max)/2;
: count=1;
: prev=a[0];

A*********r
发帖数: 564
16
嗯,好像就是这个count的问题,我以为我的会收敛的更快,容我再想想。。

【在 h**k 的大作中提到】
: 你这个程序是直接用二分法找到最大的x么?
: 如果是的话,中间for循环里找k个元素满足最小距离大于x的代码,好像不对。
: 应该是
: int count = 1;
: int pre_ele = a[0];
: for( int i=1; i: {
: if( a[i] - pre_ele >= x )
: {
: count++;

A*********r
发帖数: 564
17
我们两个的2分,找的好像不是同一个东西。。
我的2分, 是为了找出在给定的1..N之中,找出一个最大的X, 使得X有k个元素的子集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
从你得到的总复杂度来看,你还是对X的范围进行了二分的,所以才会有LogN.
你最后得到的复杂度,其实是已经在两次二分的基础上得到的(对0..M一次,对0..N一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).
我自己都快绕晕了。。

【在 h**6 的大作中提到】
: 楼上的代码好像仍然不是很对,这是两个版本的代码,假设a已排序。
: 由于a排序需要额外的复杂度,因此两个版本的复杂度差别不是很大。
: 逐个查找,O(M),总复杂度O(MlogM+MlogN)
: bool findelements(int* a, int M, int K, int x)
: {
: int prev = a[0];
: int count = 1;
: for(int i=1; i: {
: if(a[i] >= prev+x)

A*********r
发帖数: 564
18
自己顶一下,希望han6出来确认一下,呵呵。。

集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素
curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).

【在 A*********r 的大作中提到】
: 我们两个的2分,找的好像不是同一个东西。。
: 我的2分, 是为了找出在给定的1..N之中,找出一个最大的X, 使得X有k个元素的子集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
: 从你得到的总复杂度来看,你还是对X的范围进行了二分的,所以才会有LogN.
: 你最后得到的复杂度,其实是已经在两次二分的基础上得到的(对0..M一次,对0..N一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).
: 我自己都快绕晕了。。

h**k
发帖数: 3368
19
han6就是实现的你改进的DP算法的最后的那个二分查找。他是想说明这里用线性查找和
二分查找效率差不多。

集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素
curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).

【在 A*********r 的大作中提到】
: 我们两个的2分,找的好像不是同一个东西。。
: 我的2分, 是为了找出在给定的1..N之中,找出一个最大的X, 使得X有k个元素的子集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
: 从你得到的总复杂度来看,你还是对X的范围进行了二分的,所以才会有LogN.
: 你最后得到的复杂度,其实是已经在两次二分的基础上得到的(对0..M一次,对0..N一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).
: 我自己都快绕晕了。。

f******t
发帖数: 7283
20
用上抽屉原理这道题就简单很多了:
M个数字里面要选K个,那就是说假如把这M个数字分成K-1份,不管你怎么选那K个数,
其中至少有2个是来自那K-1份中的其中某一份的。既然半径是定义为distance最小的,
那处在“同一份”里的数就有可能构成最小距离喽(比如说,用均值不等式)。问题就
转化为,怎么分那K-1份?解决这个并不难,我记得多年前在某市的奥数竞赛二试题里
有过这个题,既然那时候都是人脑算答案的,所以我觉得其实这道题不一定要写程序才
能算出结果。
临睡前一分钟随便想到的东东,我不保证一定100%对哦。
相关主题
刚刚被Google电面了,真失败求教移除数组重复元素的时间复杂度!!
an interview question谷歌电面回馈
一个题问uber的一道题
进入JobHunting版参与讨论
A*********r
发帖数: 564
21
嗯,对的,他实现的是在M上的二分查找,不过跟我在DP版本给出的思路不太一样,也
不能直接用在那里。
不知道他给出的code到底针对的是DP版本还是非DP版本,呵呵。。

【在 h**k 的大作中提到】
: han6就是实现的你改进的DP算法的最后的那个二分查找。他是想说明这里用线性查找和
: 二分查找效率差不多。
:
: 集,所以会是O(M*LogN)。。你的2分,是在M个元素中二分,找出一个最小的合适元素
: curr,使得最后K元素子集的半径为X,所以复杂度是O(K*logM).
: 一次), 所以总复杂度等于sort的复杂度+O(k*logM*logN).

h**6
发帖数: 4160
22
我其实是回你上一个帖子:
“有一点想不通,如何只用O(M)判断是否能找到K个元素,使得他们之间的最小距离大
于等于给定的X?”
给出两个版本的代码,分别是O(M)和O(KlogM)复杂度。
两个函数的声明完全相同
bool findelements(int* a, int M, int K, int x)
判断已排序的长度为 M 的数组 a 中,是否存在 K 个元素的子集,其半径不小于 x ,返回值
为 bool 类型。
A*********r
发帖数: 564
23
haha, everything make sense now.
Thanks for clarification.

,返回值

【在 h**6 的大作中提到】
: 我其实是回你上一个帖子:
: “有一点想不通,如何只用O(M)判断是否能找到K个元素,使得他们之间的最小距离大
: 于等于给定的X?”
: 给出两个版本的代码,分别是O(M)和O(KlogM)复杂度。
: 两个函数的声明完全相同
: bool findelements(int* a, int M, int K, int x)
: 判断已排序的长度为 M 的数组 a 中,是否存在 K 个元素的子集,其半径不小于 x ,返回值
: 为 bool 类型。

k*******n
发帖数: 8891
24
re
1 (共1页)
进入JobHunting版参与讨论
相关主题
谷歌电面回馈G家电面题目
问uber的一道题请教一道算法题
Fibonacci序列的时间和空间复杂度是多少呀?两个Sorted Array,找K smallest element
也问一个median的问题关于求the kth smallest in two sorted array
Young table的搜索最快能到多少阿?问个不常见的排列组合题(或者集合子集问题)
复杂度讨论一下careercup上的一道题,找周边全是1的最大子方阵
请教一道题没人上题,我来上一道吧
onsite回来刚刚被Google电面了,真失败
相关话题的讨论汇总
话题: dp话题: count话题: int话题: 复杂度话题: 元素