PHP实现螺旋矩阵(螺旋数组)

今天碰到一个比较有意思的问题, 就是把A到Y这25个字母以下面的形式输出出来

ABCDE
PQRSF
OXYTG
NWVUH
MLKJI
问题很有意思,就是转圈圈把字母填到表格中,要输出这样的格式,其实就需要构造一个下面这样的表格
12345
161718186
152425207
142322218
131211109
这其实是一个螺旋矩阵的问题, 这跟下面这个问题本质是一样的:
给定一个行数row和列数cols, 输出对应的螺旋数组, 
比如3行5列
12345
121314156
1110987
又比如5行3列
123
12134
11145
10156
987
解决这个问题可能有多种办法, 但是我的思路是按上、右、下、左四个方向不停的往里面画圈,如下图
思路有了,接下来就是写代码的事了,闲话少说,上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
  * 根据传入的行数和列数生成螺旋数组
  * @author chenqionghe
  * @param int $row 行数
  * @param int $col 列数
  * @return array
  */
function rotationSort( $row =5, $col =5)
{
     $k =1;
     $result = array ();
     $small = $col < $row ? $col : $row ;
     $count = ceil ( $small / 2);
     for ( $i =0; $i < $count ; $i ++)
     {
         $maxRight = $col -1- $i ; //右边最大坐标
         $maxBottom = $row -1 - $i ; //下面最大坐标
         for ( $j = $i ; $j <= $maxRight ; $j ++)           //构造上边一条线  纵坐标最小,横坐标递增
         {
             $result [ $i ][ $j ] = $k ++;
         }
         for ( $j = $i ; $j < $maxBottom ; $j ++)           //构造右边一条线 纵坐标递增,横坐标最大
         {
             $result [ $j +1][ $maxRight ] = $k ++;
         }
         for ( $j = $maxRight -1; $j >= $i ; $j --)          //构造下边一条线 纵坐标最大,横坐标递减
         {
             if ( $result [ $maxBottom ][ $j ]) break ;
             $result [ $maxBottom ][ $j ] = $k ++;
         }
         for ( $j = $maxBottom -1; $j > $i ; $j --)           //构造左边一条线 纵坐标递减,横坐标最小
         {
             if ( $result [ $j ][ $i ]) break ;
             $result [ $j ][ $i ] = $k ++;
         }
     }
     return $result ;
}
该函数由伟大的诗人chenqionghe撰写, 调用时传数两个参数行数和列数,即可返回螺旋数组,
好人做到底吧,再定义一个以表格输出的方式,打印该螺旋数组直观一点,方法如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
  * 以table格式输出数组
  * @param $result 螺旋数组
  * @param $row 行数
  * @param $col 列数
  */
function printArray( $result , $row , $col )
{
     echo '<table border=1 style="width:500px;">' ;
     for ( $i =0; $i < $row ; $i ++)
     {
         echo '<tr>' ;
         for ( $j =0; $j < $col ; $j ++)
         {
             echo '<td style="padding: 50px;">' . $result [ $i ][ $j ]. '</td>' ;
         }
         echo '<tr>' ;
     }
     echo '</table>' ;
}
然后,我们来调用一下上面的方法,生成一个5*5的螺旋数组
1
2
3
4
$row = 5;
$col = 5;
$arr = rotationSort( $row , $col );
printArray( $arr , $row , $col );
执行结果如下
我了个乖乖,只能用perfect来形容。
 
现在,我们回到那个输出25个字母A-Y的问题,解决这个问题更简单了,就是以0-到24为键,A-Y为值,定义数组就行了,如下:
1
$arr = array ( 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'N' , 'M' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' ,);
输出的时候稍做改动即能输出A-Y的螺旋数组,完整代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
/**
  * 根据传入的行数和列数生成螺旋数组
  * @author chenqionghe
  * @param int $row 行数
  * @param int $col 列数
  * @return array
  */
function rotationSort( $row =5, $col =5)
{
     $k =1;
     $result = array ();
     $small = $col < $row ? $col : $row ;
     $count = ceil ( $small / 2);
     for ( $i =0; $i < $count ; $i ++)
     {
         $maxRight = $col -1- $i ; //右边最大坐标
         $maxBottom = $row -1 - $i ; //下面最大坐标
         for ( $j = $i ; $j <= $maxRight ; $j ++)           //构造上边一条线  纵坐标最小,横坐标递增
         {
             $result [ $i ][ $j ] = $k ++;
         }
         for ( $j = $i ; $j < $maxBottom ; $j ++)           //构造右边一条线 纵坐标递增,横坐标最大
         {
             $result [ $j +1][ $maxRight ] = $k ++;
         }
         for ( $j = $maxRight -1; $j >= $i ; $j --)          //构造下边一条线 纵坐标最大,横坐标递减
         {
             if ( $result [ $maxBottom ][ $j ]) break ;
             $result [ $maxBottom ][ $j ] = $k ++;
         }
         for ( $j = $maxBottom -1; $j > $i ; $j --)           //构造左边一条线 纵坐标递减,横坐标最小
         {
             if ( $result [ $j ][ $i ]) break ;
             $result [ $j ][ $i ] = $k ++;
         }
     }
     return $result ;
}
/**
  * 以table格式输出数组
  * @param $rotationArr 要输出的内容
  * @param $result 螺旋数组
  * @param $row 行数
  * @param $col 列数
  */
function printArray( $rotationArr , $result , $row , $col )
{
     echo '<table border=1 style="width:500px;">' ;
     for ( $i =0; $i < $row ; $i ++)
     {
         echo '<tr>' ;
         for ( $j =0; $j < $col ; $j ++)
         {
             //echo '<td style="padding: 50px;">'.$result[$i][$j].'</td>';
             echo '<td style="padding: 50px;">' . $rotationArr [ $result [ $i ][ $j ]-1]. '</td>' ;
         }
         echo '<tr>' ;
     }
     echo '</table>' ;
}
$arr = array ( 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'N' , 'M' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' ,);
$row = 5;
$col = 5;
$rotationArr = rotationSort( $row , $col );
printArray( $arr , $rotationArr , $row , $col );
最终输出结果如下:


转载地址:http://www.cnblogs.com/chenqionghe/p/4765802.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值