将整数数组转换为非负整数数组

时间:2011-06-01 03:12:20

标签: algorithm sorting

从一个整数数组开始,以便值的总和为正整数S。以下例程始终以相同的步骤结束,并且结果相同。这是为什么?

从数组x = [x_0, x_1, ..., x_N-1]开始,使所有x_i都是整数。虽然存在否定条目,但请执行以下操作:

  • 选择任何索引i,以便x_i < 0

  • x_i(负数)添加到x_(i-1 % N)

  • x_i(负数)添加到x_(i+1 % N)

  • x_i替换为-x_i(正数)。

此过程维护x_0 + x_1 + ... + x_N-1 = S的属性。对于任何给定的起始数组x,无论在任何步骤选择哪个索引,通过这些步骤的次数与结果向量相同。对于我来说,这个过程在有限的时间内终止是不明显的(至少对我而言),更不用说具有这种不错的不变性。

实施例

选择x = [4 , -1, -2]并翻转x_1开始,结果为

[4, -1, -2]
[3, 1, -3]
[0, -2, 3]
[-2, 2, 1]
[2, 0, -1]
[1, -1, 1]
[0, 1, 0]

另一方面,将x_2翻转为开始

[4, -1, -2]
[2, -3, 2]
[-1, 3, -1]
[1, 2, -2]
[-1, 0, 2]
[1, -1, 1]
[0, 1, 0]

如果您选择x_2而不是x_0来翻转第三个数组,那么最后一种方法会为此解决方案提供从第三个向下反转的数组。在所有情况下,6个步骤都会导致[0,1,0]

我有一个争论,为什么这是真的,但在我看来过于复杂(它与Coxeter groups)有关。有没有人有更直接的方式来思考为什么会这样?即使找到这个终止的原因也会很棒。

奖励指向任何找到确定给定数组步骤数的方法(不经过整个过程)。

3 个答案:

答案 0 :(得分:4)

我将负值向两个方向推出,直到它们衰减为止。由于加法是可交换的,因此处理元素的顺序无关紧要。

答案 1 :(得分:4)

我认为无论你在每一步选择什么索引,最简单的方法就是看看为什么输出向量和步数是相同的,就是把问题看作一堆矩阵和向量乘法。

对于x包含3个组件的情况,请将x视为3x1向量:x = [x_0 x_1 x_2]'(其中'是转置操作)。循环的每次迭代都将选择翻转x_0,x_1,x_2中的一个,并且它在x上执行的操作与乘以下列矩阵之一相同:

      -1  0  0               1  1  0                1  0  1
s_0 =  1  1  0       s_1 =   0 -1  0        s_2 =   0  1  1
       1  0  1               0  1  1                0  0 -1

其中乘以s_0是指数i=0s_1对应i=1s_2对应i=2时执行的操作。使用此视图,您可以将算法解释为在每次迭代时将相应的s_i矩阵乘以x。因此,在开始时翻转x_1的第一个示例中,算法计算:s_1*s_2*s_0*s_1*s_2*s_1[4 -1 -2]' = [0 1 0]'

您选择的索引不影响最终输出向量的事实源于s矩阵的两个有趣属性。首先,s_i*s_(i-1)*s_i = s_(i-1)*s_i*s(i-1),其中i-1以模n为模,即矩阵数。此属性是唯一需要查看为什么在包含3个元素的示例中得到相同结果的属性:

s_1*s_2*s_0*s_1*s_2*s_1 = s_1*s_2*s_0*(s_1*s_2*s_1) = s_1*s_2*s_0*(s_2*s_1*s_2),对应于在开始时选择x_2,最后:

s_1*s_2*s_0*s_2*s_1*s_2 = s_1*(s_2*s_0*s_2)*s_1*s_2 = s_1*(s_0*s_2*s_0)*s1*s2,对应于选择在开始时翻转x_2,然后选择在第三次迭代中翻转x_0

第二个属性仅在x包含4个或更多元素时适用。每当s_i*s_k = s_k*s_i k <= i-2再次以模i-2计算n时,x -1 0 0 0 1 1 0 0 1 0 0 0 1 0 0 1 s_0 = 1 1 0 0 s_1 = 0 -1 0 0 s_2 = 0 1 1 0 s_3 = 0 1 0 0 0 0 1 0 0 1 1 0 0 0 -1 0 0 0 1 1 1 0 0 1 0 0 0 1 0 0 1 1 0 0 0 -1 。当x_1有4个元素时考虑矩阵的形式时,此属性很明显:

x_3

第二个属性基本上表示您可以交换发生非冲突翻转的顺序。例如,在4元素向量中,如果您首先翻转x_3然后翻转x_1,则这与首次翻转{{1}}然后翻转{{1}}具有相同的效果。< / p>

答案 2 :(得分:0)

这是观察N何时被3整除...可能没用,但我觉得要写下来。

w(complex)成为1的原始立方根;即w^3 = 11 + w + w^2 = 0。例如,w = cos(2pi/3) + i*sin(2pi/3)

考虑总和x_0 + x_1*w + x_2*w^2 + x_3 + x_4*w + x_5*w^2 + ...。也就是说,将序列的每个元素乘以w的连续幂并将它们全部加起来。

每一步都会发生一些有趣的事情。

从序列中考虑三个连续的数字[a, -b, c],其中b为正。假设这些元素与w的幂相对应,使得这三个数字对总和贡献a - b*w + c*w^2

现在在中间元素上执行步骤。

在此步骤之后,这些数字会为总和贡献(a-b) + b*w + (c-b)*w^2

但是自1 + w + w^2 = 0b + b*w + b*w^2 = 0以来。因此,我们可以将其添加到上一个表达式以获取a + 2*b*w + c。这与我们之前的步骤非常相似。

换句话说,该步骤仅将3*b*w添加到总和中。

如果三个连续的数字排在w的权力之后(例如)a*w - b*w^2 + c,那么该步骤将会添加3*b*w^2

换句话说,无论w的权力如何与这三个数字对齐,该步骤都会增加3*b3*b*w3*b*w^2之和。

不幸的是,从w^2 = -(w+1)开始,这实际上并没有产生稳定增长的功能。所以,正如我所说,可能没用。但似乎一个合理的策略是为每个位置寻求一个“签名”,每个位置随着每一步单调变化......