[英]Print 2D array values in spiral sequence
我想以螺旋順序打印一個數組。 對於大小為 3x3、4x4 等的數組。 我的代碼工作正常,但對於 3x5、4x6 或 5x8 尺寸,輸出錯誤,僅返回第一次迭代。
這是我的簡單代碼:
private function _spiral($rows, $cols, array $array) {
$offset = 0;
while($offset < ($rows - 1)){
for($col = $offset; $col <= $cols - 1; $col++){
print($array[$offset][$col] . ' ');
}
$offset++;
$cols--;
for($row = $offset; $row < $rows; $row++){
print($array[$row][$cols] . ' ');
}
$rows--;
for($col = $cols - 1; $col >= $offset; $col--){
print($array[$rows][$col] . ' ');
}
for($row = $rows; $row >= $offset; $row--){
print($array[$row][$offset - 1] . ' ');
}
}
}
3 行 4 列示例:
$array = array(
array(00,01,02,03),
array(10,11,12,13),
array(20,21,22,23)
)
這個數組的預期結果是0 1 2 3 13 23 22 21 20 10 11 12
,但我的函數的輸出在 10 后停止。
對於 4 行 4 列:
$array = array(
array(00,01,02,03),
array(10,11,12,13),
array(20,21,22,23),
array(30,31,32,33)
)
...它應該返回0 1 2 3 13 23 33 32 31 30 20 10 11 12 22 21
,這就是我的代碼返回的內容。
但我希望這兩種情況都適用於我的代碼。 如何更正代碼以在第一種和其他情況下也產生正確的輸出?
您的代碼存在一些問題:
它不會以相同的方式處理四個遍歷方向。 這四個方向有四個循環,但在某些情況下,您將<=
作為循環結束條件,在其他情況下<
,在某些情況下,條件是負 1,而在其他情況下則不是。
它沒有規定何時所有元素都被第一個或第二個內循環打印,因此在某些情況下,剩余的循環將打印已經打印的元素。
外循環條件不檢查是否還有需要遍歷的列。 僅測試此類行是不夠的。
盡管您可以嘗試修復您的代碼,但我認為最好從頭開始,考慮到解決方案對於所有四個方向都應該是對稱的。 這是一個重要的發展直覺反應:點對稱。 這將導致更少的代碼和更少的錯誤。
您想遍歷數組中的一個維度(行或列),直到到達數組的邊界或已打印的元素。 然后你想向右轉 90° 並一遍又一遍地重復完全相同的邏輯。 因此,如果您的代碼在這些不同的方向上看起來不同,那么就有問題了。
我將分享兩個實現。 兩者都將使用“當前”單元的概念,並讓它以螺旋運動的方式移動。
第一個解決方案使用相同的代碼處理沿行的后退或前進,類似地,它有一段代碼用於向前或向后遍歷列。 所以這個解決方案有兩個內部循環,一個用於沿行遍歷,另一個用於沿列遍歷。 在其中一行或一列被遍歷被保持在所述方向$direction
可變的,其中,1之間翻轉和-1在外部循環的每個執行:
function _spiral(array $array) {
// No need to have the number of rows and columns passed as arguments:
// We can get that information from the array:
$rows = count($array);
$cols = count($array[0]);
// Set "current" cell to be outside array: it moves into it in first inner loop
$row = 0;
$col = -1;
$direction = 1; // Can be 1 for forward and -1 for backward
while ($rows > 0 and $cols > 0) {
// Print cells along one row
for ($step = 0; $step < $cols; $step++) {
$col += $direction;
print $array[$row][$col] . ' ';
}
// As we have printed a row, we have fewer rows left to print from:
$rows--;
// Print cells along one column
for ($step = 0; $step < $rows; $step++) {
$row += $direction;
print $array[$row][$col] . ' ';
}
// As we have printed a column, we have fewer columns left to print from:
$cols--;
// Now flip the direction between forward and backward
$direction = -$direction;
}
}
請注意第一個內環和第二個內環之間的完美對稱。
在第二種解決方案中,這種對稱性的使用更進一步,以便僅用一個來替換兩個內環。 為此,我們必須放棄對行和列使用單獨的變量,並使用與維度相關的大小概念:
function _spiral(array $array) {
// This version of the function aims to treat rows and columns in the same way,
// They are just another dimension, but all the logic is exactly the same:
// $size[] has the number of rows in $size[0] and number of columns in $size[1]
$size = Array(count($array), count($array[0]));
// $current[] has the current row in $current[0] and current column in $current[1]
$current = Array(0, -1);
// $direction[] has the current row-traversal direction in $direction[0]
// and column-traveral direction in $direction[1]
$direction = Array(1, 1);
$dimension = 0; // Which dimension to traverse along, can be 0 for row, 1 for column
while ($size[$dimension] > 0) {
// Switch dimension (row to column, column to row), to traverse along
$dimension = 1 - $dimension;
// Print one line along that dimension, in its current direction
for ($step = 0; $step < $size[$dimension]; $step++) {
$current[$dimension] += $direction[$dimension];
print $array[$current[0]][$current[1]] . ' ';
}
// As we have printed a line, we have fewer left to print from:
$size[1 - $dimension]--;
// Now flip the direction between forward and backward for this dimension:
$direction[$dimension] = -$direction[$dimension];
}
}
一年多后應要求:這是一個版本,允許您選擇從哪個角落開始,以及是否逆時針而不是順時針。 這個函數不會打印結果,而是返回一個一維數組,帶有螺旋序列。 通過這種方式,您可以自己決定如何處理結果:打印它,或者……無論如何。
function spiral(array $array, $startRight = false, $startBottom = false,
$counterClockWise = false) {
// This version allows to select which corner to start from, and in which direction.
// $size[] has the number of rows in $size[0] and number of columns in $size[1]
$size = [count($array), count($array[0])];
// $direction[] has the current row-traversal direction in $direction[0]
// and column-traversal direction in $direction[1]
$direction = [$startBottom ? -1 : 1, $startRight ? -1 : 1];
// Which dimension to traverse along: false means row, true means column.
// Every one of the optional arguments will flip the first dimension to use:
$dimension = ($startBottom xor $startRight xor $counterClockWise);
// $current[] has the current row in $current[0] and current column in $current[1]
$current = [$startBottom * (count($array)-1), $startRight * (count($array[0])-1)];
// Go back one step, outside of the grid
$current[!$dimension] -= $direction[!$dimension];
while ($size[$dimension] > 0) {
// Switch dimension (row to column, column to row), to traverse along
$dimension = !$dimension;
// Print one line along that dimension, in its current direction
for ($step = 0; $step < $size[$dimension]; $step++) {
$current[$dimension] += $direction[$dimension];
$result[] = $array[$current[0]][$current[1]]; // store in new array
}
// As we have printed a line, we have fewer left to print from:
$size[!$dimension]--;
// Now flip the direction between forward and backward for this dimension:
$direction[$dimension] = -$direction[$dimension];
}
return $result; // Return the resulting spiral as a 1D array
}
查看它在eval.in 上運行
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.