Algorithm 在一维数组中寻找有界最近邻
假设我们有一些布尔值数组:Algorithm 在一维数组中寻找有界最近邻,algorithm,performance,sorting,computer-science,complexity-theory,Algorithm,Performance,Sorting,Computer Science,Complexity Theory,假设我们有一些布尔值数组: A = [0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 0 1 1 1 1 0 0 0 ... 0] 数组是通过对数据流执行分类来构造的。数组中的每个元素都对应于给定一小块数据的分类算法的输出。答案可能包括重新构造数组以提高解析效率 该数组是伪随机的,即1和0的组倾向于成束存在(但不一定总是) 给定一些索引,i,找到最接近A[i]的至少n零组的最有效方法是什么?对于简单的情况,取n=1 编辑:组应至少有n个零。同样,对于简单的情况,
A = [0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 0 1 1 1 1 0 0 0 ... 0]
数组是通过对数据流执行分类来构造的。数组中的每个元素都对应于给定一小块数据的分类算法的输出。答案可能包括重新构造数组以提高解析效率
该数组是伪随机的,即1
和0
的组倾向于成束存在(但不一定总是)
给定一些索引,i
,找到最接近A[i]
的至少n
零组的最有效方法是什么?对于简单的情况,取n=1
编辑:组应至少有n个零。同样,对于简单的情况,这意味着至少1个零
EDIT2:此搜索将执行
o(n)
次,其中n
是数组的大小。(具体地说,它的n/c
,其中c
是某个固定的持续时间。如果在大小为n的数组上有n个查询,那么简单的方法将花费O(n^2)时间
您可以通过合并观察结果来优化这一点,即不同的组大小的数量按sqrt(n)的顺序排列,因为如果我们有一组大小为1、一组大小为2、一组大小为3,依此类推,我们得到的最不同的组大小是1+2+3+…+n是n*(n+1)/2,因此按n^2的顺序排列,但数组的大小为n,因此不同组大小的数量按sqrt(n)的顺序排列
O(n*log(n)*sqrt(n))=O(n^1.5*log(n))
这比O(n^2)好
我认为你可以通过创建一个结构来将其归结为O(n^1.5),该结构具有所有不同的组大小,但不仅包含该大小的组,还包含大于该大小的组。这将是创建该结构的时间复杂性,并且回答所有n个查询将更快O(n*log(sqrt(n))*log(n))我想,所以没关系
例如:
[0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0, 1, 0, 0] -- 0 indexed array
hashmap = {1:[0], 2:[15, 18], 7:[5]}
search(i = 7, n = 2) {
binary search in {2:[15, 18], 7:[5]}
return min(15, 5)
}
在这个解决方案中,我组织数据,以便您可以使用二进制搜索
O(logn)
来查找至少具有一定大小的最近组
我首先从数组中创建一组零,然后将每组零放入包含大小s
或更大的所有组的列表中,这样当您想要查找最近的一组大小为s
或更大的组时,您只需在列表中运行一个二进制搜索,该列表包含大小为s
或更大的所有组
缺点是在将组放入列表的预处理过程中,O(n*m)
(我想,请检查我)的时间和空间效率,n
是零组的数量,m
是组的最大大小,尽管实际上效率可能更好
代码如下:
publicstaticvoidmain(字符串[]args){
字节[]byteArray=null;
List groups=Group.getGroupsOfZeros(byteArray);
GroupsBySize GroupsBySize=新的GroupsBySize(组);
int指数=12;
int-atLeastSize=5;
g组=groupsBySize.GetNearestGroupofAtlestSize(索引,AtlestSize);
System.out.println(“最近的组为“+g.x1+”:“+g.x2+”),大小为“+g.size”);
}
找到最接近A[i]的至少n个零的组的最有效方法是什么
如果我们不受预处理时间和资源的限制,最有效的方法似乎是O(1)
时间和O(n*sqrt n)
空间,存储所有可能查询的答案。(要实现这一点,请运行下面的算法,列出所有可能的查询,即数组中与每个索引成对的每个不同的零组大小。)
如果一次向我们提供所有的n/c
查询,我们可以在O(n log n)
时间内生成完整的结果集
从左侧遍历一次,从右侧遍历一次。对于每次遍历,从一个平衡的二叉树开始,查询按零组大小排序(查询中的n
),其中每个节点都有一个已排序的查询索引列表(所有i
s以及此特定的n
)
在每次迭代中,当注册一个零组时,更新所有查询,使n
等于并小于此零组大小,从节点中删除所有相等和较低的索引,并保留它们的记录(由于索引列表已排序,我们只需在其等于或低于当前索引时删除列表的标题),并将零组的当前索引也存储在节点中(“上次看到的”零组索引)。如果节点中没有剩余i
s,请将其删除
遍历之后,将每个节点的“上次看到的”零组索引分配给该节点中剩余的i
s
public static class Group {
final public int x1;
final public int x2;
final public int size;
public Group(int x1, int x2) {
assert x1 <= x2;
this.x1 = x1;
this.x2 = x2;
this.size = x2 - x1 + 1;
}
public static final List<Group> getGroupsOfZeros(byte[] arr) {
List<Group> listOfGroups = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
int x1 = i;
for (++i; i < arr.length; i++)
if (arr[i] != 0)
break;
int x2 = i - 1;
listOfGroups.add(new Group(x1, x2));
}
}
return Collections.unmodifiableList(listOfGroups);
}
public static final Group binarySearchNearest(int i, List<Group> list) {
{ // edge cases
Group firstGroup = list.get(0);
if (i <= firstGroup.x2)
return firstGroup;
Group lastGroup = list.get(list.size() - 1);
if (i >= lastGroup.x1)
return lastGroup;
}
int lo = 0;
int hi = list.size() - 1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
Group currGroup = list.get(mid);
if (i < currGroup.x1) {
hi = mid - 1;
} else if (i > currGroup.x2) {
lo = mid + 1;
} else {
// x1 <= i <= x2
return currGroup;
}
}
// intentionally swapped because: lo == hi + 1
Group lowGroup = list.get(hi);
Group highGroup = list.get(lo);
return (i - lowGroup.x2) < (highGroup.x1 - i) ? lowGroup : highGroup;
}
}
public static class GroupsBySize {
private List<List<Group>> listOfGroupsBySize = new ArrayList<>();
public GroupsBySize(List<Group> groups) {
for (Group group : groups) {
// ensure internal array can groups up to this size
while (listOfGroupsBySize.size() < group.size) {
listOfGroupsBySize.add(new ArrayList<Group>());
}
// add group to all lists up to its size
for (int i = 0; i < group.size; i++) {
listOfGroupsBySize.get(i).add(group);
}
}
}
public final Group getNearestGroupOfAtLeastSize(int index, int atLeastSize) {
if (atLeastSize < 1)
throw new IllegalArgumentException("group size must be greater than 0");
List<Group> groupsOfAtLeastSize = listOfGroupsBySize.get(atLeastSize - 1);
return Group.binarySearchNearest(index, groupsOfAtLeastSize);
}
}
public static void main(String[] args) {
byte[] byteArray = null;
List<Group> groups = Group.getGroupsOfZeros(byteArray);
GroupsBySize groupsBySize = new GroupsBySize(groups);
int index = 12;
int atLeastSize = 5;
Group g = groupsBySize.getNearestGroupOfAtLeastSize(index, atLeastSize);
System.out.println("nearest group is (" + g.x1 + ":" + g.x2 + ") of size " + g.size);
}