获取螺旋矩阵的对角线值

7
我有一个n*n的螺旋矩阵。

if N = 4

then matrix :

 7  8  9 10   
 6  1  2 11  
 5  4  3 12   
16 15 14 13

if N = 3

 7 8 9
 6 1 2
 5 4 3 

我希望能获取这个螺旋矩阵的对角线值。

n=4 的情况下,对角线的值应为 7,1,3,13,10,2,4,16。

我可以通过将此矩阵存储在数组中并遍历每个对角线值来完成此操作。
是否有更好的方法来获取这些值。


如果不是用数组,你是如何存储矩阵的呢?能否把你目前的代码贴出来? - Peter Gordon
现在我正在存储在数组中,但它可以是任何其他数据类型。 - Ajay
2
@pgmann 请参考乌拉姆螺旋。楼主询问是否可以在不以螺旋方式存储矩阵中的数字或者根本不存储任何地方的情况下识别对角线上的数字。 - Susam Pal
你只对角落到角落的对角线感兴趣吗?乌拉姆螺旋展示了其他对角线上显著更多的质数字符串。我想知道是否有一个函数来确定那些最大值... - Jeff Puckett
@JeffPuckettII 是的 - Ajay
显示剩余2条评论
3个回答

2
为了得到主对角线上的数字,我们可以注意到这些值是
1 = 1
1 + 2 = 3
1 + 2 + 4 = 7
1 + 2 + 4 + 6 = 13

因此,通用公式为 1 + (sum i = 0 to k of 2*i),其中 k = 0、1、2 等。简化后,我们得到 k^2 + k + 1,其中 k = 0、1、2 等。

在 PHP 中,我们可以通过以下方式生成这些内容:

function mainDiagonal($n) {
    $values = array();

    for ($k = 0; $k < $n; $k++) {
        $values[] = $k*$k + $k + 1;
    }

    return $values;
}

为了得到偶数N的反对角线上的数字,我们可以看到:
2 = 2
2 + 2 = 4
2 + 2 + 6 = 10
2 + 2 + 6 + 6 = 16

如果我们将这个模式应用于更大的矩阵,我们可以得到一般公式:
对于k = 0、1、2、...,求和i = 0到k的floor(i/2)*4 + 2
类似地,对于奇数N,我们发现公式为:
对于k = 0、1、2、...,1 + 求和i = 0到k的ceil(i/2)*4
在PHP中,我们可以通过以下方式生成它们:
function antiDiagonal($n) {
    $values = array();

    if ($n % 2 == 0) {
        for ($k = 0; $k < $n; $k++) {
            $accum = 0;

            for ($j = 0; $j <= $k; $j++) {
                $accum += floor($j/2)*4 + 2;
            }

            $values[] = $accum;
        }
    } else {
        for ($k = 0; $k < $n; $k++) {
            $accum = 1;

            for ($j = 0; $j <= $k; $j++) {
                $accum += ceil($j/2)*4;
            }

            $values[] = $accum;
        }
    }

    return $values;
}

注意,k的最大值比矩阵的维数小1。

将这些函数结合起来,我们得到:

array_unique(array_merge(mainDiagonal($n), antiDiagonal($n)))

在 n = 3(或任何奇数值的 N)的情况下,反对角线上的值是错误的。 - Ajay
我认为你的方法很棒,但是这个函数目前只返回一个对角线。 - Jeff Puckett
我正在说话的同时添加另一个。 - Rose Kunkel
2
不错,那我们加上print_r(array_unique(array_merge(mainDiagonal($n),antiDiagonal($n))));怎么样? - Jeff Puckett
感谢@WilliamKunkel提供的反对和主对角线方法,我编写了一段代码,我认为这是最好的。再次非常感谢您的帮助。 - Ajay
显示剩余2条评论

1
问题可以分为4个部分:找到每个象限中对角线上的数字。有四个象限,所以我们有四个轮辐:
  1. 西北(NW)轮辐
  2. 东北(NE)轮辐
  3. 西南(SW)轮辐
  4. 东南(SE)轮辐
例如,在您的乌拉姆螺旋图中,当N为偶数时。
  1. NW轮辐有1、7...
  2. NE轮辐有2、10...
  3. SW轮辐有4、16...
  4. SE轮辐有3、13...
问题进一步分为两种情况:
  1. N为偶数。
  2. N为奇数。

情况1:N为偶数

这里是每个轮辐的公式:
NW spoke: f(n) = 4*n*n + 2*n + 1
NE spoke: g(n) = 4*n*n + 4n + 2
SW spoke: h(n) = 4*n*n + 8*n + 4
SE spoke: i(n) = 4*n*n + 6*n + 3

其中 n = 0, 1, 2, ...

对于 4x4 矩阵,计算以下集合:

{f(0), f(1), g(0), g(1), h(0), h(1), i(0), i(1)}

它产生了对角线上的值:
{1, 7, 2, 10, 4, 16, 3, 13}

一般来说,对于一个N x N的矩阵,当N为偶数时,计算以下集合以获取对角线上的值:
{ f(0), ..., f(N/2 - 1),
  g(0), ..., g(N/2 - 1),
  h(0), ..., h(N/2 - 1),
  i(0), ..., i(N/2 - 1) }

案例2:N为奇数

在您的乌拉姆螺旋图示中,当N为奇数时,每个轮辐的公式如下:

NW spoke: f(n) = 4*n*n + 2*n + 1
NE spoke: g(n) = 4*n*n + 4*n + 1
SW spoke: h(n) = 4*n*n + 1
SE spoke: i(n) = 4*n*n - 2*n + 1

其中n = 0, 1, 2, ...

请注意,f(0) = g(0) = h(0) = i(0) = 1。

对于3x3,计算以下集合:

{f(0), f(1), g(1), h(1), i(1)}

它产生以下对角线值:
{1, 7, 9, 5, 3}.

一般来说,对于一个NxN的矩阵,在N为奇数时,计算以下集合以获取对角线上的值:
{ f(0), ..., f((N - 1)/2,
  g(0), ..., g((N - 1)/2),
  h(0), ..., h((N - 1)/2),
  i(0), ..., i((N - 1)/2) }

PHP代码

最后,这是一个演示我上面所讨论的内容的PHP程序。

<?php
function ulam_diag($N)
{
    $result = array();

    if ($N % 2 == 0) {
        for ($n = 0; $n < $N / 2; $n++) {
            $result[] = 4*$n*$n + 2*$n + 1;
            $result[] = 4*$n*$n + 4*$n + 2;
            $result[] = 4*$n*$n + 8*$n + 4;
            $result[] = 4*$n*$n + 6*$n + 3;
        }
    } else {
        $result[] = 1;
        for ($n = 1; $n <= ($N - 1) / 2; $n++) {
            $result[] = 4*$n*$n + 2*$n + 1;
            $result[] = 4*$n*$n + 4*$n + 1;
            $result[] = 4*$n*$n + 1;
            $result[] = 4*$n*$n - 2*$n + 1;         
        }
    }

    sort($result);
    return $result;
}

print_r(ulam_diag(4));
print_r(ulam_diag(3));
?>

输出:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 7
    [5] => 10
    [6] => 13
    [7] => 16
)
Array
(
    [0] => 1
    [1] => 3
    [2] => 5
    [3] => 7
    [4] => 9
)

这里是一个 Ideone 上的代码: http://ideone.com/F9jaC0

如果您想知道我是如何得出这些公式的,那么 Ulam 螺旋的四个轮辐已经有了成熟的结果。以下是参考资料:

  1. https://oeis.org/A054569 (你的插图中的西北轮辐)
  2. https://oeis.org/A016754 (你的插图中的东北轮辐)
  3. https://oeis.org/A053755 (你的插图中的西南轮辐)
  4. https://oeis.org/A054554 (你的插图中的东南轮辐)

你的插图中的 Ulam 螺旋与流行的 Ulam 螺旋表示方式不同,因此我采用了这些众所周知的结果,并调整了每个公式的 n 偏移量,以使其适用于你的 Ulam 螺旋。这些调整留给读者作为练习。;-)


当N = 3时,“1”应放在哪个位置? - Ajay
“1”是所有轮辐的一部分。这就是为什么 f(0) = g(0) = h(0) = i(0) = 1。因此,我们总是将“1”作为对角线值之一输出(在PHP代码中硬编码),然后计算整数n = 1、2、...的f(n)、g(n)、h(n)、i(n)。 - Susam Pal

0

对于矩阵中的每一行,我们都有两个对角线值。为了获得这两个值,我使用了主对角线和反对角线的两个位置(x1,y1)和(x2,y2)。

好的,我写了这段代码:

<?php
    function getSpiralDiagonal($spiralArr,$N){
        $diagonalValueCount = $N*2;
        $xIndexMainDiagonal = 0;
        $yIndexMainDiagonal = 0;
        $xIndexAntiDiagonal = 0;
        $yIndexAntiDiagonal = $N-1;
        while($diagonalValueCount > 0){
            //checking for same position
            if($yIndexMainDiagonal == $yIndexAntiDiagonal){
                echo $spiralArr[$xIndexMainDiagonal][$yIndexMainDiagonal].'<br>';
            }else{
                echo $spiralArr[$xIndexMainDiagonal][$yIndexMainDiagonal].'<br>';
                echo $spiralArr[$xIndexAntiDiagonal][$yIndexAntiDiagonal].'<br>';
            }

            $xIndexMainDiagonal++;
            $yIndexMainDiagonal++;
            $xIndexAntiDiagonal++;
            $yIndexAntiDiagonal--;
            $diagonalValueCount -= 2;
        }
    }

    $spiralArr = array(array('7','8','9'),array('6','1','2'),array('5','4','3'));
    getSpiralDiagonal($spiralArr,3);
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接