- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我尝试用 O(kn log n) 实现平衡的 K-D 树,我使用预排序的 K 数组(每个索引的排序数组)来获得 O(kn log n),并使用中位数来获得平衡树。
我面临的问题是,大多数情况下,某些级别的中值,例如 x 轴的中值,可能会在另一个后续级别再次选择,例如 y 轴。
我试图通过使用选定的 x 值作为基准将 y 排序数组分成两个数组来解决这个问题,但这种方法不会产生平衡树。
知道如何用 O(kn log n) 得到 K-D 平衡树吗?
编辑
转自维基 https://en.wikipedia.org/wiki/K-d_tree
Alternative algorithms for building a balanced k-d tree presort the data prior to building the tree. They then maintain the order of the presort during tree construction and hence eliminate the costly step of finding the median at each level of subdivision. Two such algorithms build a balanced k-d tree to sort triangles in order to improve the execution time of ray tracing for three-dimensional computer graphics. These algorithms presort n triangles prior to building the k-d tree, then build the tree in O(n log n) time in the best case.[5][6] An algorithm that builds a balanced k-d tree to sort points has a worst-case complexity of O(kn log n).[7] This algorithm presorts n points in each of k dimensions using an O(n log n) sort such as Heapsort or Mergesort prior to building the tree. It then maintains the order of these k presorts during tree construction and thereby avoids finding the median at each level of subdivision.
谁能提供上面提供的这样的算法?
编辑
想出了一个方法,但如果中位数的特定轴有任何重复值,它就不起作用。
例如
x1 = [ (0, 7), (1, 3), (3, 0), (3, 1), (6, 2) ] y1 = [ (3, 0), (3, 1) , (6, 2), (1, 3), (0, 7)]
x 轴的中位数是 3。因此,当我们想要拆分数组 y11 和 y12 时,我们必须使用 > 和 < 将 y 数组左右分布,并将枢轴作为分隔符。
如果特定轴上的中位数 a 重复,则不能保证其中之一是正确的
考虑x轴上的分区,完成上面第一步分区的例子后x1数组没有问题:
median=(3,0)
The pivot = 3 // is it's the median of x axis
y11[],y12[]
for(i = 0 ; i < x1.size;i++)
if(y1[i].getX()<pivot)
y11.add(y1[i])
else
if(y1[i].getX()>pivot)
y12.add(y1[i])
这将导致 y11 = [(2 ,1) , (1, 3), (0, 7) ] y12 = [ (6,2) ]
知道如何处理这种情况吗?还是有其他预排序kd-tree预排序算法O(kn log n)?
最佳答案
详细说明我的评论(可能还有 Anony-Mousse's answer):
构建 KD 树时预排序的关键思想是在拆分过程中保持顺序。开销看起来相当高,与重新排序(和k-select)的比较基准似乎是有序的。
一些原理验证 Java 源代码:
package net.*.coder.greybeard.sandbox;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
/** finger exercise pre-sorting & split for KD-tree construction
* (re. https://stackoverflow.com/q/35225509/3789665) */
public class KDPreSort {
/** K-dimensional key, dimensions fixed
* by number of coordinates in construction */
static class KKey {
public static KKey[] NONE = {};
final Comparable[]coordinates;
public KKey(Comparable ...coordinates) {
this.coordinates = coordinates;
}
/** @return {@code Comparator<KKey>} for coordinate {@code n}*/
static Comparator<KKey> comparator(int n) { // could be cached
return new Comparator<KDPreSort.KKey>() { @Override
public int compare(KKey l, KKey r) {
return l.coordinates[n]
.compareTo(r.coordinates[n]);
}
};
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(
Arrays.deepToString(coordinates));
sb.setCharAt(0, '(');
sb.setCharAt(sb.length()-1, ')');
return sb.toString();
}
}
// static boolean trimLists = true; // introduced when ArrayList was used in interface
/** @return two arrays of {@code KKey}s: comparing smaller than
* or equal to {@code pivot} (according to {@code comp)},
* and greater than pivot -
* in the same order as in {@code keys}. */
static KKey[][] split(KKey[] keys, KKey pivot, Comparator<KKey> comp) {
int length = keys.length;
ArrayList<KKey>
se = new ArrayList<>(length),
g = new ArrayList<>(length);
for (KKey k: keys) {
// pick List to add to
List<KKey>d = comp.compare(k, pivot) <= 0 ? se : g;
d.add(k);
}
// if (trimLists) { se.trimToSize(); g.trimToSize(); }
return new KKey[][] { se.toArray(KKey.NONE), g.toArray(KKey.NONE) };
}
/** @return two arrays of <em>k</em> arrays of {@code KKey}s:
* comparing smaller than or equal to {@code pivot}
* (according to {@code comp)}, and greater than pivot,
* in the same order as in {@code keysByCoordinate}. */
static KKey[][][]
splits(KKey[][] keysByCoordinate, KKey pivot, Comparator<KKey> comp) {
final int length = keysByCoordinate.length;
KKey[][]
se = new KKey[length][],
g = new KKey[length][],
splits;
for (int i = 0 ; i < length ; i++) {
splits = split(keysByCoordinate[i], pivot, comp);
se[i] = splits[0];
g[i] = splits[1];
}
return new KKey[][][] { se, g };
}
// demo
public static void main(String[] args) {
// from https://stackoverflow.com/q/17021379/3789665
Integer [][]coPairs = {// {0, 7}, {1, 3}, {3, 0}, {3, 1}, {6, 2},
{12, 21}, {13, 27}, {19, 5}, {39, 5}, {49, 63}, {43, 45}, {41, 22}, {27, 7}, {20, 12}, {32, 11}, {24, 56},
};
KKey[] someKeys = new KKey[coPairs.length];
for (int i = 0; i < coPairs.length; i++) {
someKeys[i] = new KKey(coPairs[i]);
}
//presort
Arrays.sort(someKeys, KKey.comparator(0));
List<KKey> x = new ArrayList<>(Arrays.asList(someKeys));
System.out.println("by x: " + x);
KKey pivot = someKeys[someKeys.length/2];
Arrays.sort(someKeys, KKey.comparator(1));
System.out.println("by y: " + Arrays.deepToString(someKeys));
// split by x
KKey[][] allOrdered = new KKey[][] { x.toArray(KKey.NONE), someKeys },
xSplits[] = splits(allOrdered, pivot, KKey.comparator(0));
for (KKey[][] c: xSplits)
System.out.println("split by x of " + pivot + ": "
+ Arrays.deepToString(c));
// split "higher x" by y
pivot = xSplits[1][1][xSplits[1][1].length/2];
KKey[][] ySplits[] = splits(xSplits[1], pivot, KKey.comparator(1));
for (KKey[][] c: ySplits)
System.out.println("split by y of " + pivot + ": "
+ Arrays.deepToString(c));
}
}
(在没有投入太多精力的情况下,没有在 SE 上找到合适的答案/实现。您的示例的输出没有说服力,较长的示例,我不得不重新格式化才能相信它。
代码看起来很难看,很可能是因为它是:如果愿意,请重新阅读 licence of code posted on SE , 一访Code Review .)(考虑有投票、接受和奖励赏金,并重新访问 Anony-Mousse 的回答。)
关于arrays - O(kn log n) 的算法平衡 K-D 树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35225509/
在使用 requests 库中的状态代码时,我遇到了一些奇怪的事情。每个 HTTP 状态代码都有一个常量,有些具有别名(例如,包括 200 的复选标记): url = 'https://httpbin
这是我得到的代码,但我不知道这两行是什么意思: o[arr[i]] = o[arr[i]] || {}; o = o[arr[i]]; 完整代码: var GLOBAL={}; GLOBAL.name
所以这个问题的答案What is the difference between Θ(n) and O(n)? 指出“基本上,当我们说算法是 O(n) 时,它也是 O(n2)、O(n1000000)、O
这是一个快速的想法;有人会说 O(∞) 实际上是 O(1) 吗? 我的意思是它不依赖于输入大小? 所以在某种程度上它是恒定的,尽管它是无限的。 或者是唯一“正确”的表达方式 O(∞)? 最佳答案 无穷
这是真的: log(A) + log(B) = log(A * B) [0] 这也是真的吗? O(log(A)) + O(log(B)) = O(log(A * B)) [1] 据我了解 O(f
我正在解决面试练习的问题,但我似乎无法找出以下问题的时间和空间复杂度的答案: Given two sorted Linked Lists, merge them into a third list i
我了解 Big-Oh 表示法。但是我该如何解释 O(O(f(n))) 是什么意思呢?是指增长率的增长率吗? 最佳答案 x = O(n)基本上意味着 x <= kn对于一些常量 k . 因此 x = O
我正在编写一个函数,该函数需要一个对象和一个投影来了解它必须在哪个字段上工作。 我想知道是否应该使用这样的字符串: const o = { a: 'Hello There' }; funct
直觉上,我认为这三个表达式是等价的。 例如,如果一个算法在 O(nlogn) + O(n) 或 O(nlogn + n) 中运行(我很困惑),我可以假设这是一个O(nlogn) 算法? 什么是真相?
根据 O'Reilly 的 Python in a Nutshell 中的 Alex Martelli,复杂度类 O(n) + O(n) = O(n)。所以我相信。但是我很困惑。他解释说:“N 的两个
O(n^2)有什么区别和 O(n.log(n)) ? 最佳答案 n^2 的复杂性增长得更快。 关于big-o - 大 O 符号 : differences between O(n^2) and O(n
每当我收到来自 MS outlook 的电子邮件时,我都会收到此标记 & nbsp ; (没有空格)哪个显示为?在 <>. 当我将其更改为 ISO-8859-1 时,浏览器页面字符集编码为 UTF-8
我很难理解 Algorithms by S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani - page 24 中的以下陈述它们将 O(n) 的总和表
我在面试蛋糕上练习了一些问题,并在问题 2给出的解决方案使用两个单独的 for 循环(非嵌套),解决方案提供者声称他/她在 O(n) 时间内解决了它。据我了解,这将是 O(2n) 时间。是我想错了吗,
关于 Java 语法的幼稚问题。什么 T accept(ObjectVisitorEx visitor); 是什么意思? C# 的等价物是什么? 最佳答案 在 C# 中它可能是: O Accept(
假设我有一个长度为 n 的数组,我使用时间为 nlogn 的排序算法对它进行了排序。得到这个排序后的数组后,我遍历它以找到任何具有线性时间的重复元素。我的理解是,由于操作是分开发生的,所以时间是 O(
总和 O(1)+O(2)+ .... +O(n) 的计算结果是什么? 我在某处看到它的解决方案: O(n(n+1) / 2) = O(n^2) 但我对此并不满意,因为 O(1) = O(2) = co
这个问题在这里已经有了答案: 11 年前关闭。 Possible Duplicate: Plain english explanation of Big O 我想这可能是类里面教的东西,但作为一个自学
假设我有两种算法: for (int i = 0; i 2)更长的时间给定的一些n - 其中n这种情况的发生实际上取决于所涉及的算法 - 对于您的具体示例, n 2)分别时间,您可能会看到: Θ(n)
这个问题在这里已经有了答案: Example of a factorial time algorithm O( n! ) (4 个回答) 6年前关闭。 我见过表示为 O(X!) 的 big-o 示例但
我是一名优秀的程序员,十分优秀!