什么是时间效率和节省空间的算法,用于将离散范围的整数(比如间隔I1 [A..B],其中B> = A)线性映射到另一个更大的整数范围(比如一个区间) I2 [C..D]其中D> = C)?
为了简单地在此呈现,第二范围I2的大小被约束为大于或等于第一范围I1,换句话说,D-C> = B-A。
因此,I1中的每个整数映射到I2中包含的一个或多个相应整数的集合(因为I2的大小大于I1的大小)。相反,I2中的每个整数都映射回I1中恰好一个唯一的对应整数。
因此,存在两种期望的算法,其在两个提供的整数间隔的域中操作:间隔I1 [A..B]和间隔I2 [C..D](其中B> = A且D> = C和DC> = BA)
算法A1:给定I1中包含的整数X,计算I2中相应的线性映射整数集。将其表示为A1(I1,I2,X)= [M..N],其中[M..N]是I2的子间隔。
算法A2:给定区间I2中包含的整数Y,计算I1中的单个对应整数。将其表示为A2(I1,I2,Y)= X。
算法A2必须是A1的对称逆。也就是说,对于I1中的所有X:A1(I1,I2,X)= [M..N],则对于[M..N]中的所有Y:A2(I1,I2,Y)= X
显然,由于此问题仅限于整数,因此映射可能不完全是线性的。例如,如果I1包含三个整数[1..3],而I2包含四个整数[4..7],则I1中的两个整数将在I2中具有单个映射,而I1中的第三个整数将具有I2中的两个映射。来自I1的具有两个映射的特定整数是无关紧要的。重要的是,无论算法A1选择哪个整数(X)具有两个映射(Y和Y + 1),算法A2必须将相同的两个Y值从I1映射回原始X.
算法A1和A2应该创建从I1到I2的最可能的线性映射。换句话说,如果间隔I1具有大小J并且间隔I2具有大小K(并且回想起K> = J),则I1的每个整数具有TRUNC(K / J)映射或TRUNC(K / J)+1映射。进入I2。
算法应该消耗恒定的空间,因此由一组代数方程组成,这些方程可能使用截断整数除法和模运算,以及其他基本数学函数。换句话说,算法不能为需要空间来存储表中每个映射的映射创建表,因为整数区间的大小可以达到2 ^ 64.
编辑:例如,假设间隔I1 = [0..2]且间隔I2 = [0..4]。一个正确的解决方案可能是:
Algorithm A1 Algorithm A2
X=0, Y=[0..1] Y=0, X=0
X=1, Y=[2..3] Y=1, X=0
X=2, Y=[4] Y=2, X=1
Y=3, X=1
Y=4, X=2
另一个同样正确的解决方案是:
Algorithm A1 Algorithm A2
X=0, Y=0 Y=0, X=0
X=1, Y=[1..2] Y=1, X=1
X=2, Y=[3..4] Y=2, X=1
Y=3, X=2
Y=4, X=2
INCORRECT解决方案将是:
Algorithm A1 Algorithm A2
X=0, Y=[0..1] Y=0, X=0
X=1, Y=[2..3] Y=1, X=1
X=2, Y=[4] Y=2, X=1
Y=3, X=2
Y=4, X=2
上述解决方案不正确。虽然A1确实将[0..2]线性映射到[0..4],而A2确实将[0..4]线性地映射回[0..2],但问题是A2不是A1的倒数。例如,对于X = 0,A1(0)的一个值是Y = 1,但A2(1)给出X = 1(而不是原始值0)。
答案 0 :(得分:1)
我建议使用模块化映射,而不是使用区间和截断,只需按照数字顺序将 i1 的元素映射到 i2 ,然后根据需要进行换行。这是Python中的代码(为了清晰和通用,有一些过于简单和冗余的赋值),以及范围[2:5]和[4:13]
的示例代码:
def alg_1(x, interval_1, interval_2):
# Map X, an element of interval 1,
# to a list of elements in interval 2.
lo_1 = interval_1[0]
hi_1 = interval_1[1]
lo_2 = interval_2[0]
hi_2 = interval_2[1]
range_1 = hi_1 - lo_1 + 1
range_2 = hi_2 - lo_2 + 1
pos_1 = x - lo_1
base_val = pos_1 + lo_2
y = range(base_val, hi_2+1, range_1)
return y
def alg_2(y, interval_1, interval_2):
# Map Y, an element of interval 2,
# to its corresponding element in interval1.
lo_1 = interval_1[0]
hi_1 = interval_1[1]
lo_2 = interval_2[0]
hi_2 = interval_2[1]
range_1 = hi_1 - lo_1 + 1
range_2 = hi_2 - lo_2 + 1
pos_2 = y - lo_2
x = lo_1 + pos_2 % range_1
return x
i1 = (2, 5)
i2 = (4, 13)
print "X Y"
for val in range(i1[0], i1[1]+1):
print val, alg_1(val, i1, i2)
print ""
print "Y X"
for val in range(i2[0], i2[1]+1):
print val, alg_2(val, i1, i2)
输出:
X Y
2 [4, 8, 12]
3 [5, 9, 13]
4 [6, 10]
5 [7, 11]
Y X
4 2
5 3
6 4
7 5
8 2
9 3
10 4
11 5
12 2
13 3
<强>问题强>
对于X =&gt; Y映射,此方法返回映射值列表。此列表的大小为|i2| / |i1|
。那可以接受吗?当这个比率上升到大约2 ^ 25时,它会变慢。
如果您愿意,可以返回 xrange 而不是范围;这是序列的生成器,而不是序列本身。
答案 1 :(得分:1)
您可以使用multiplicative inverse和偏移量轻松完成此操作。首先减去A.然后进行乘法逆计算,并通过添加C来翻译结果。
要反转它,减去D,执行乘法逆计算的反函数,然后添加A.
这很有效。我过去使用它效果很好。