让我们假设,例如,我有一个三维网格/数组,其中轴的运行范围是1到1000(或0到999等效)。这个数组有1000 ^ 3个元素。
我想使用Java以确定的方式将0到1000 ^ 3范围内的单个整数映射到此数组。优选地,该解决方案适用于任何尺寸N.
以下是此类函数的伪编码示例:
public Vector<int> nthElement( Vector<int> dims, int n )
因此,如果我将其称为nthElement([1000, 1000, 1000], 0)
,则会返回[0, 0, 0]
,而nthElement([1000, 1000, 1000], 1001)
会返回[999, 1, 0]
之类的内容。
解决方案应该是N维,而不是我的例子中的3。
答案 0 :(得分:3)
这是正确的映射算法:
map([X, Y, Z, T, ...], N) = [
N mod X,
N div X mod Y,
N div X div Y mod Z,
N div X div Y div Z (mod ...)?
...
]
或递归
map([X, Y, Z, T, ...], N) = [N mod X, map([Y, Z, T, ...], N div X)]
其中,div B为Floor(A / B)。
答案 1 :(得分:1)
你可以这样做:
a = Number % (1000 * 1000)
b = (Number / 1000) % 1000
c = Number / (1000 * 1000)
这是一个映射(唯一),你可以简单地做反向
注意2/3 = 0不是.6666
答案 2 :(得分:1)
检查这个
List<Integer> nthElement( List<Integer> dims, int n ){
List<Integer> res = new ArrayList<Integer>(dims.size());
for(Integer cur : dims){
if(n <= 0 ){
res.add(0);
} else {
n -= cur;
res.add(n >= 0 ? cur -1 : cur + n );
}
}
return res;
}
UPD 用法示例
//create list with 3 dimensions using Guava
List<Integer> dims = ImmutableList.of(1000, 1000, 1000);
//or with standard JDK
//List<Integer> dims = new ArrayList<Integer>(3);dims.add(1000);dims.add(1000);dims.add(1000);
System.out.println(nthElement(dims, 0));
System.out.println(nthElement(dims, 1000));
System.out.println(nthElement(dims, 1001));
System.out.println(nthElement(dims, 2001));
将打印
[0, 0, 0]
[999, 0, 0]
[999, 1, 0]
[999, 999, 1]
答案 3 :(得分:0)
您可能正在寻找的是Cantor pairing function。它是为NxN定义的,因此您可以将其用于任意大的尺寸。如维基百科页面所述,它可以归纳为一个维数为n的数组,在你的情况下,n = 3就可以了。
上面的页面还解释了反转函数,因此您可以从给定的数字中获取数组中的坐标,这正是您想要的nthElement
。
当然,康托尔只定义了一种可能的方式来走过一个二维场。还有其他可能的步行,但这是最流行的方式。
编辑:我应该提一下,如果您的数组具有矩形尺寸,则Cantor配对功能将采用最大尺寸的尺寸。因此,相关的数字不再在您的数组中连续出现。 F.ex.大小为1000x2的数组将被视为1000x1000数组,与实际数组中的条目对应的数字将只是数字0..1000 * 1000的非连续列表。 但是,如果您的三个维度始终相同,则可以完全忽略这一点。
回应评论:逐行和Cantor配对只是走过矩阵空间的不同方式。 Cantor配对的一个优点是它是在自然数上定义的,因此如果您没有矩阵尺寸的精确值,或者矩阵随时间增长,也适用。