获得螺旋矩阵的对角线值

时间:2016-06-21 16:29:26

标签: php algorithm math

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

  

如果N = 4

     

然后矩阵:

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

如果N = 3

 7 8 9
 6 1 2
 5 4 3 

我想得到这个螺旋矩阵的对角线值。

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

我可以通过将此矩阵存储在数组中并遍历每个对角线值来实现此目的 有没有更好的方法来获得这些价值。

3 个答案:

答案 0 :(得分:2)

要获得主对角线上的数字,我们可以注意到值是

1 = 1
1 + 2 = 3
1 + 2 + 4 = 7
1 + 2 + 4 + 6 = 13

因此,对于k = 0,1,2,......,通式为1 +(和i = 0到k为2 * i) 简化这一点,对于k = 0,1,2,......

,我们得到k ^ 2 + k + 1

在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

如果我们对更大的矩阵继续使用这种模式,我们会看到通用公式

总和i = 0到楼层的k(i / 2)* 4 + 2,对于k = 0,1,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)))

答案 1 :(得分:1)

问题可以分为4个部分:在每个象限中找到沿对角轮辐的数字。有四个象限,所以我们有四个辐条:

  1. 西北(NW)发言
  2. 东北(NE)发言
  3. 西南(SW)发言
  4. 东南(SE)发言
  5. 例如,在你的Ulam螺旋图中,当N是偶数时。

    1. NW发言有1,7,......
    2. NE说话有2,10,......
    3. SW说话有4,16,......
    4. SE发言有3个,13个......
    5. 问题进一步细分为两种情况:

      1. N是偶数。
      2. N很奇怪。
      3. 案例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}
        

        通常,对于NxN矩阵,当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是奇数

        在你的Ulam螺旋图中,当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(NW在你的插图中说了)
        2. https://oeis.org/A016754(NE在你的插图中说了)
        3. https://oeis.org/A053755(SW在你的插图中说了)
        4. https://oeis.org/A054554(SE在你的插图中说了)
        5. 你的插图中的Ulam螺旋与Ulam螺旋的流行表现不同,因此我采用了这些众所周知的结果并调整了每个公式的n的偏移量,以便它与你的Ulam螺旋一起使用。这些调整留给读者练习。 ; - )

答案 2 :(得分: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);
?>