php笔试算法题:顺时针打印矩阵坐标-蛇形算法

这几天参加面试,本来笔试比较简单,但是在面试的时候,技术面试官说让我现场写一个算法,顺时针打印矩阵的坐标,如图所示

 

顺序为,0,1,2,3,4,9,14,19,24,23,22,21,20,15,10,5,6,7,8,13,18,17,16,11,12

假设 0的坐标为(0,0),1的坐标为(0,1),5的坐标为(1,0)其他以此类推。

题目是打印出来顺序的坐标。

当场这道题我没写出来,后来面试官让我回家写,然后发到他的邮箱。回到家网上找了一下,也没有好的解决方案,只好自己写了。

总体思路采用一个大循环控制,循环条件当前的最大纵坐标不小于最小纵坐标,并且当前小横坐标不小于最大横坐标时,循环终止,然后再按照上右下左的顺序分四个小循环遍历。

     第一步:实现等高等宽的矩阵(x=y)的坐标遍历。
     第二步:采用记录标志的方式改进,实现x!=y或x=y矩阵的遍历。
 
第一步代码实现:
  1 /**
  2  * [printXY 顺时针遍历等高等宽矩阵坐标]
  3  * @param  integer $n [矩阵宽高]
  4  * @return string     [坐标字符串]
  5  */
  6 function printXY($n=1) 
  7 {
  8     if($n<=1) return '(0,0)';
  9 
 10     $minTopX    = 0;    //当前最小横坐标
 11     $maxRightY  = $n-1; //当前最大纵坐标
 12     $maxBottomX = $n-1; //当前最大横坐标
 13     $minLeftY   = 0;    //当前最小纵坐标
 14 
 15     $sortXY = ''; //定义一个空字符串,用于接收坐标
 16 
 17     //当当前的最大纵坐标不小于最小纵坐标,并且当前小横坐标不小于最大横坐标时,循环终止
 18     while ($minLeftY <= $maxRightY && $minTopX <= $maxBottomX) {
 19         //循环的顺序为,上->右->下->左
 20         // 当前上面一行
 21         for($j = $minLeftY; $j <= $maxRightY; $j++) {
 22             $sortXY .= '('.$minTopX.','.$j.') ';
 23         }
 24         $minTopX++;
 25 
 26         // 当前右边一行
 27         for($i = $minTopX; $i <= $maxBottomX; $i++) {
 28             $sortXY .= '('.$i.','.$maxRightY.') ';
 29         }
 30         $maxRightY--;
 31 
 32         // 当前底部一行
 33         for($j = $maxRightY; $j >= $minLeftY; $j--) {
 34             $sortXY .=  '('.$maxBottomX.','.$j.') ';
 35         }
 36         $maxBottomX--;
 37 
 38         // 当前左边一行
 39         for($i = $maxBottomX; $i >= $minTopX; $i--) {
 40             $sortXY .= '('.$i.','.$minLeftY.') ';
 41         }
 42         $minLeftY++;
 43     }
 44     return $sortXY;
 45 }

第二步的实现代码:

 1 /**
 2  * [printXY2 顺时针遍历矩阵坐标]
 3  * @param  integer $x [矩阵宽度]
 4  * @param  integer $y [矩阵高度]
 5  * @return string     [坐标字符串]
 6  */
 7 function printXY2($x=1,$y=1) 
 8 {
 9     if($x<=1 && $y<=1) return '(0,0)';
10 
11     $minTopX    = 0;    //最小横坐标
12     $maxRightY  = $y-1; //最大纵坐标
13     $maxBottomX = $x-1; //最大横坐标
14     $minLeftY   = 0;    //最小纵坐标
15 
16     $sortXY = ''; //定义一个空字符串,用于接收坐标
17     $sortXYFlagArr[0][0] = false; //定义一个二维数组,记录是否被使用过。
18 
19     //当当前的最大纵坐标不小于最小纵坐标,并且当前小横坐标不小于最大横坐标时,循环终止
20     while ($minLeftY <= $maxRightY && $minTopX <= $maxBottomX) {
21         //循环的顺序为,上->右->下->左
22 
23         // 当前上面一行
24         for($j = $minLeftY; $j <= $maxRightY; $j++) {
25             if(!isset($sortXYFlagArr[$minTopX][$j])){
26                 $sortXY .= '('.$minTopX.','.$j.') ';
27                 $sortXYFlagArr[$minTopX][$j] = true;
28             }
29         }
30         $minTopX++;
31 
32         // 当前右边一行
33         for($i = $minTopX; $i <= $maxBottomX; $i++) {
34             if(!isset($sortXYFlagArr[$i][$maxRightY])){
35                 $sortXY .= '('.$i.','.$maxRightY.') ';
36                 $sortXYFlagArr[$i][$maxRightY] = true;
37             }
38         }
39         $maxRightY--;
40 
41         // 当前底部一行
42         for($j = $maxRightY; $j >= $minLeftY; $j--) {
43             if(!isset($sortXYFlagArr[$maxBottomX][$j])){
44                 $sortXY .=  '('.$maxBottomX.','.$j.') ';
45                 $sortXYFlagArr[$maxBottomX][$j] = true;
46             }
47         }
48         $maxBottomX--;
49 
50         // 当前左边一行
51         for($i = $maxBottomX; $i >= $minTopX; $i--) {
52 
53             if(!isset($sortXYFlagArr[$i][$minLeftY])){
54                 $sortXY .= '('.$i.','.$minLeftY.') ';
55                 $sortXYFlagArr[$i][$minLeftY] = true;
56             }
57         }
58         $minLeftY++;
59     }
60     return $sortXY;
61 }

请大家指正。

posted @ 2015-11-18 22:40  GeorgeHao  阅读(671)  评论(0编辑  收藏  举报