簡體   English   中英

以螺旋順序打印二維數組值

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM