Arrays 根据需要拆分自然数数组
我有两个自然数数组Arrays 根据需要拆分自然数数组,arrays,numbers,Arrays,Numbers,我有两个自然数数组{Ai}和{Bi}。所有元素的和都相等 我需要将两个数组中的每个元素拆分为三个自然数: Ai=A1i+A2i+A3i Bi=B1i+B2i+B3i 这样,A1的所有元素之和等于B1的所有元素之和,并且对于所有其他对而言相同 我最初忘记的重要部分是: A1j、A2j、A3j中的每个元件应介于Aj/3-2和Aj/3+2之间,或至少等于这些数字中的一个 B1j、B2j、B3j中的每个元素应介于Bj/3-2和Bj/3+2之间,或至少等于这些数字中的一个 所以数组的元素必须分成几乎相等的
{Ai}
和{Bi}
。所有元素的和都相等
我需要将两个数组中的每个元素拆分为三个自然数:
Ai=A1i+A2i+A3i
Bi=B1i+B2i+B3i
这样,A1的所有元素之和等于B1的所有元素之和,并且对于所有其他对而言相同
我最初忘记的重要部分是:
A1j、A2j、A3j中的每个元件应介于Aj/3-2和Aj/3+2之间,或至少等于这些数字中的一个
B1j、B2j、B3j中的每个元素应介于Bj/3-2和Bj/3+2之间,或至少等于这些数字中的一个
所以数组的元素必须分成几乎相等的部分
我在寻找一些更优雅的解决方案,而不仅仅是计算两个阵列的所有可能变量。您应该查找 在这种情况下,它似乎与一些类似 对于查找A1_i、A2_i、A3_i,您应该递归执行:
def find_numbers(n, a, arr):
if arr[n] not empty:
return
if n == 0:
arr[n].append(a)
return
if a.size() > 2:
return
t = n
for each element of a:
t -= element
for i = 0 to :
find_numbers(n, append(a, i), arr)
我们使用arr
,这样我们就不需要为每个数字计算可能的组合的多次。如果在一段时间后查看调用树,此函数将返回来自arr
的组合,而不会再次计算它们。
在您的主要通话中:
arr = []
for each n in A:
find_number(n, [], arr)
for each n in B:
find_number(n, [], arr)
现在您有了arr[n]中每个n的所有组合。
我知道这是问题的一个子部分,但从arr中为每个a_I,B_I找到正确的组合与此非常相似阅读我给你的链接非常重要,这样你就可以理解背后的基本理论。你应该查一下基本原理 在这种情况下,它似乎与一些类似 对于查找A1_i、A2_i、A3_i,您应该递归执行:
def find_numbers(n, a, arr):
if arr[n] not empty:
return
if n == 0:
arr[n].append(a)
return
if a.size() > 2:
return
t = n
for each element of a:
t -= element
for i = 0 to :
find_numbers(n, append(a, i), arr)
我们使用arr
,这样我们就不需要为每个数字计算可能的组合的多次。如果在一段时间后查看调用树,此函数将返回来自arr
的组合,而不会再次计算它们。
在您的主要通话中:
arr = []
for each n in A:
find_number(n, [], arr)
for each n in B:
find_number(n, [], arr)
现在您有了arr[n]中每个n的所有组合。
我知道这是问题的一个子部分,但从arr中为每个a_I,B_I找到正确的组合与此非常相似阅读我给你的链接非常重要,这样你才能理解背后的基本理论
我寻找一些更优雅的解决方案,而不仅仅是计算两个数组的所有可能变量
应该可以将它们分开,使A1、A2和A3的总和接近a的三分之一,而B的总和相同。只需将所有值精确设为三分之一就很容易了,但对于自然数来说这是不可能的。因此,我们必须floor
results(琐碎的)并将余数均匀地分布在三个数组上(可管理的)
我不知道这是否是唯一的解决方案,但它在O(n)
中有效,我的直觉告诉我它将保存你的不变量(尽管我没有证明它):
我们也可以在不进行分割的情况下形成回路,仅将A[i]的单个单元(1)分布在A[x][i]上:
n = 3
for j=0 to n
A[j] = {}
for k=0 to |A|
A[j][i] = 0
x = 0 // rotating pointer for the next subarray
for i in A
// distribute the rest over the arrays, and rotate the pointer
for j=0 to A[i]
A[x][i]++
x++
我寻找一些更优雅的解决方案,而不仅仅是计算两个数组的所有可能变量
应该可以将它们分开,使A1、A2和A3的总和接近a的三分之一,而B的总和相同。只需将所有值精确设为三分之一就很容易了,但对于自然数来说这是不可能的。因此,我们必须floor
results(琐碎的)并将余数均匀地分布在三个数组上(可管理的)
我不知道这是否是唯一的解决方案,但它在O(n)
中有效,我的直觉告诉我它将保存你的不变量(尽管我没有证明它):
我们也可以在不进行分割的情况下形成回路,仅将A[i]的单个单元(1)分布在A[x][i]上:
n = 3
for j=0 to n
A[j] = {}
for k=0 to |A|
A[j][i] = 0
x = 0 // rotating pointer for the next subarray
for i in A
// distribute the rest over the arrays, and rotate the pointer
for j=0 to A[i]
A[x][i]++
x++
我增加了一项规定,即A1、A2和A3必须在不知道B的情况下从A计算,同样,B1、B2和B3必须在不知道A的情况下计算 要求每个A1i、A2i、A3i必须在[Ai/3–2,Ai/3+2]中,这意味着A1、A2和A3元素的总和必须分别约为A元素的三分之一。该规定迫使我们对其进行完全定义 我们将以任意顺序构造数组(例如,从元素0到最后一个元素)。在这样做时,我们将确保阵列保持几乎平衡 设x是要处理的A的下一个元素。设a为圆形(x/3)。为了计算x,我们必须在数组A1、A2和A3中加上总共3•a+r,其中r是–1、0或+1 设d为和(A1)–和(A)/3,其中和是迄今为止处理的元素。最初,d是零,因为没有处理任何元素。根据设计,我们将确保每个步骤的d为–2/3、0或+2/3 分别向A1、A2和A3追加三个值,如下所示:
- 如果r为-1,d为-2/3,则附加a+1、a-1、a-1。这将d更改为+2/3
- 如果r为-1,d为0,则附加a-1、a、a。这将d更改为–2/3
- 如果r为-1,d为+2/3,则附加a-1、a、a。这会将d更改为0
- 如果r为0,则追加a、a、a。这使d保持不变
- 如果r为+1,d为–2/3,则附加a+1、a、a。这会将d更改为0
- 如果r为+1,d为0,则附加a+1、a、a。这将d更改为+2/3
- 如果r为+1,d为+2/3,则附加-1、a+1、a+1。这将d更改为–2/3
完成演示: 在任何情况下,都会将–1、a或+1追加到数组中。a是圆形的(x/3),因此它与x/3的区别在于