- 主题:求动态区间k大 (转载)
【 在 Analog 的大作中提到: 】
: 不行吧,现在让你求的是区间第k大,比如10个数,每次给你一个区间比如3,7,求这个区间内第二大的数据
找到i<=7的节点(检查下i>=3)。这个是第一大。
再找<i的节点,就是第二大的。
每次查找都是O(log(n)).
这组平衡二叉树工具可用。
//返回=key的节点
T_Tree * BB_Tree_Find(T_Tree *sp,void *content_key,int len,
int (*Cmp_rec)(void *sp_content,void *content_key,int len));
//返回>key的节点
T_Tree * BB_Tree_GT(T_Tree *sp,void *content_key,int len,
int (*Cmp_rec)(void *s1,void *s2,int len));
//返回>=key的节点
T_Tree * BB_Tree_GTEQ(T_Tree *sp,void *content_key,int len,
int (*Cmp_rec)(void *s1,void *s2,int len));
//返回<key的节点
T_Tree * BB_Tree_LT(T_Tree *sp,void *content_key,int len,
int (*Cmp_rec)(void *s1,void *s2,int len));
//返回<=key的节点
T_Tree * BB_Tree_LTEQ(T_Tree *sp,void *content_key,int len,
int (*Cmp_rec)(void *s1,void *s2,int len));
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 ylh1969 的大作中提到: 】
:
: 找到i<=7的节点(检查下i>=3)。这个是第一大。
: 再找<i的节点,就是第二大的。
: ...................
int64_t b,e,i;
T_Tree *root,*result;
// 装载root;
b=3;
e=7;
result=BB_Tree_LTEQ(root,&e,sizeof(e),int64_cmp);
if(!result) {
// 没找到
}
i=(int64_t)result->Content;
if(i<=b) {
//出界了
}
result=BB_Tree_LT(root,&i,sizeof(i),int64_cmp);
if(!result) {
// 没找到
}
i=(int64_t)result->Content; //i就是要找的
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 你搞笑吧,比如初始化10个数
: 3 2 5 7 6 4 1 9 8 10
: 第一次查询 3 7 2 应该返回4
: ...................
二叉树是按大小排序的。
修改后依然是新的序。
此工具的修改方法是,删除原节点,加入新节点。
O(logn)
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 老兄,给的是区间的位置啊
: - 来自「最水木 for iPhone 6s」
无序数组的下标?
那么,将这一段数据加入二叉树,
进行一次MAX,再进行一次LT。或者N次LT。
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 你的时间复杂度还有保证吗?
: - 来自「最水木 for iPhone 6s」
加入是n(log(n))
查询是log(n)
n是这一段数据的数量。
--
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 你的时间复杂度还有保证吗?
: - 来自「最水木 for iPhone 6s」
可以把这一段数据弄一个数组,排序,找最大的N个。排序的复杂度也是nlogn
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 不行,需要各种操作都是O(logn*logn)
: - 来自「最水木 for iPhone 6s」
世界上有这种技术吗?
nlogn已经是各种排序技术的极限了。
我的方法,n已经是区间数据量了,比数据全集已经小了好多。
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 不行,需要各种操作都是O(logn*logn)
: - 来自「最水木 for iPhone 6s」
你的问题是有序问题,躲不开排序技术。
你需要寻找满足O(logn*logn)的排序技术。
这里只能给你提供实践上实用的技术。
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 Analog 的大作中提到: 】
: 不行,需要各种操作都是O(logn*logn)
: - 来自「最水木 for iPhone 6s」
还一个方法:
K大的buffer。
在区间内搜索一次。最大的k个在k-buffer里进行插入排序。
如果k足够小,空间开销忽略,时间是O(n),n=选择的数据集。
虽然O数不小,但是实际运行时间跟拷贝n个数据差不多。可以不必纠结O数。
如果n足够小,远远小于全集,可以认为是O(1)。
就是说,时间与全集的大小无关,只与选择集有关。
你开发的任何算法,都免不了拷贝一遍数据。这时间就算完了,你认为是O(0)都是合理的。
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*
【 在 hongdiao 的大作中提到: 】
:
: 他要的只是部分有序, 你说的排序是排全序,就是序列里面所有数都排好顺序了。 LZ要是只是第K个数。 最简单的基于快速排序变种的求第K大的算法可以做到O(N), 但是LZ要求 LogN * LogN
只进行部分排序。。
24楼的办法更好。
这里不解决理论上的偏题,怪题。仅仅解决实际问题。
--
修改:ylh1969 FROM 123.118.54.*
FROM 123.118.54.*