简体   繁体   English

需要一种有效的算法来解决这种复杂的结构

[英]Need an efficient algorithm solve this kind of complex structure

Problem Statement is : 问题陈述是:

Given 2 Dimensional array, print output for example 给定2维数组,例如打印输出

If 4 rows and 6 columns, output would be: 如果是4行和6列,则输出为:

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

I tried it is looking like square within square but when I attempted this problem, I put so many while and if loops but didn't got exact answer. 我试过它看起来像正方形在正方形内,但是当我尝试这个问题时,我放了很多while和if循环,但没有确切的答案。 If row and columns increases how to handle it? 如果行和列增加了怎么处理呢?

This is not homework. 不是功课。 I was learning solving complex structure so I need to understand it by some guidance. 我正在学习解决复杂的结构,因此我需要通过一些指导来理解它。

It's a square spiral. 这是一个方形螺旋。
You can read a bout it here: http://metacpan.org/pod/Math::PlanePath::SquareSpiral 您可以在此处阅读有关它的内容: http : //metacpan.org/pod/Math :: PlanePath :: SquareSpiral

There's an explanation for the formulas . 公式有一个解释。

Here is what I came with. 这是我附带的东西。

Variables name may be upside/down, lot of thing to enhance, remove, modify but it was fun game. 变量名称可能上下颠倒,很多事情需要增强,删除,修改,但这很有趣。

public class Test {
    public static void main(String[] args) {
        int x = 2;
        int y = 2;
        int idx = 1;
        int[][] array = new int[x][y];
        int yUpIdx = y-1;
        int yDownIdx = 0;
        int xLeftIdx = 0;
        int xRightIdx = x-1;


        while (idx < x*y) {
            for (int i = xLeftIdx; idx <= x*y && i <= xRightIdx; i++) {
                array[i][yDownIdx] = idx++;
            }
            yDownIdx++;
            for (int j = yDownIdx; idx <= x*y &&  j <= yUpIdx; j++) {
                array[xRightIdx][j] = idx++;
            }
            xRightIdx--;
            for (int i = xRightIdx; idx <= x*y &&  i>=xLeftIdx ; i--) {
                array[i][yUpIdx] = idx++;
            }
            yUpIdx--;
            for (int j = yUpIdx; idx <= x*y &&  j>=yDownIdx ; j--) {
                array[xLeftIdx][j] = idx++;
            }
            xLeftIdx++;
        }
        for (int j = 0; j < y; j++) {
            for (int i = 0 ; i < x; i++) {
                if ((array[i][j]+"").length() < 2) System.out.print(" "); 
                System.out.print(array[i][j]+" ");
            }
            System.out.println("");
        }
    }

Another solution using the same "walk in a spiral" algo: 使用相同的“螺旋行走”算法的另一种解决方案:

public class SpiralArray {
    private int[][] cells;
    private int rows;
    private int cols;

    private enum Direction {
        LEFT,
        DOWN,
        RIGHT,
        UP
    }

    public SpiralArray(int cols, int rows) {
        this.cols = cols;
        this.rows = rows;
        cells = new int[cols][rows];
        int count = 0;
        Direction direction = Direction.RIGHT;
        int x=0, y=0;
        while (count++ < cols*rows) {
            cells[x][y]=count;
            switch (direction) {
            case LEFT: 
                if ((--x<0) || (cells[x][y]>0)) {
                    y--;
                    x++;
                    direction = Direction.UP;
                }
                break;
            case RIGHT: 
                if ((++x==cols) || (cells[x][y]>0)) {
                    y++;
                    x--;
                    direction = Direction.DOWN;
                }
                break;
            case UP: 
                if ((--y<0) || (cells[x][y]>0)) {
                    x++;
                    y++;
                    direction = Direction.RIGHT;
                }
                break;
            case DOWN: 
                if ((++y==rows) || (cells[x][y]>0)) {
                    x--;
                    y--;
                    direction = Direction.LEFT;
                }
                break;
            }
        }
    }

    int get(int i, int j) {
        return cells[i][j];
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (int y=0; y<rows; y++) {
            for (int x=0; x<cols; x++) {
                sb.append(cells[x][y]).append("\t");
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(new SpiralArray(6, 4));
    }


}

I hope this idea can get you started: 我希望这个想法可以帮助您入门:

void solve2DArray(bool[][] 2DArray, int i, int j, int numMoves)
{                               
     2DArray[i][j] = true;   // Mark current position as visited
     // Perhaps a print statement here
     if(right is not visited and can move right)
       // move right
     else if(down is not visited and can move down)
       // move down
     // ...
     // ...
}

I'd probably create an NxM integer array, initialized to zero. 我可能会创建一个NxM整数数组,初始化为零。 Set nextNumber to 1, position to 0,0, and direction to left-to-right . nextNumber设置为1,将position为0,0,将direction设置left-to-right Check the position for being outside the array, and check the cell at position for zero. 检查position是否在数组之外,并检查position为零的单元格。 If position is OK and the cell is zero store nextNumber there and increment nextNumber . 如果position确定并且单元格为零,则在其中存储nextNumber并递增nextNumber Then, based on direction , increment position . 然后,根据direction ,增加position

If the cell at position is non-zero, or one of the indices of position is < 0 or >= the array size, you need to change direction. 如果position的像元非零,或者position的索引之一为<0或> =数组大小,则需要更改方向。 First back up position by 1, using the existing direction. 首先使用现有方向将position备份1。 Then pick a new direction that is 90 degrees from the current value, increment position , and try again. 然后选择一个与当前值成90度的新direction ,增加position ,然后重试。

When you can't go any direction you're done -- print the array. 当您无法完成任何方向时,请打印阵列。

(Probably a few boundary conditions I mishandled above, but that's one basic algorithm.) (上面我可能会处理一些边界条件,但这是一个基本算法。)

(Hint: Write a subroutine to increment/decrement position based on direction .) (提示:编写一个子程序以根据direction增加/减少position 。)

I guess you can just create a worm that travels through your array: 我想您可以创建一条蠕虫传播通过您的阵列:

public class Worm {
    public static void main(String[] args) {
        int[][] outArray = runWormRun(6, 4);
        printArray(outArray);
    }

    private static void printArray(int[][] outArray) {
        for (int j = 0; j < outArray[0].length; j++) {
            for (int i = 0; i < outArray.length; i++) {
                System.out.print(String.format("%02d ", outArray[i][j]));
            }
            System.out.println();
        }
    }

    private static int[][] runWormRun(int w, int h) {
        int[][] output = new int[w][h];

        int counter = 0;
        int wormX = 0, wormY = 0;
        int minX = 0, maxX = w - 1, minY = 0, maxY = h - 1;
        int dirX = 0, dirY = 1;
        while (counter < w * h) {
            output[wormX][wormY] = ++counter;
            // let the worm walk
            wormX += dirX;
            wormY += dirY;
            // update direction of worm for next iteration
            if ((dirX != 0 && dirY != 1) && wormX == minX && wormY == minY) { // upper left border (and not yet rotated correctly
                dirX = 0; dirY = 1; minY++;
            }
            if ((dirX != -1 && dirY != 0) && wormX == maxX && wormY == minY) { // upper right border
                dirX = -1; dirY = 0; maxX--;
            }
            if ((dirX != 0 && dirY != -1) && wormX == maxX && wormY == maxY) { // lower right border
                dirX = 0; dirY = -1; maxY--;
            }
            if ((dirX != 1 && dirY != 0) && wormX == minX && wormY == maxY) { // lower left border
                dirX = 1; dirY = 0; minX++;
            }
        }
        return output;
    }
}

And yes, my worm travels in the other direction, because I want you to think a bit too and understand, what I was doing. 是的,我的蠕虫朝着另一个方向传播,因为我希望您也多想一点并了解我在做什么。 Because I think that this is homework. 因为我认为这是家庭作业。 (If that's true, would you please consider adding the "homework" tag to your question?) (如果是这样,您是否可以考虑在问题中添加“作业”标签?)

EDIT: Ooops, does not exactly, what it should do. 编辑:哎呀,不完全是,它应该做什么。 No time now, will look into that in the evening. 现在没有时间,将在晚上进行调查。

Another take: 另取:

public class Test {
  enum Dir {
    R(0,1), L(0,-1), D(1,0), U(-1,0);
    public final int rowd, cold;
    private Dir(int rowd, int cold) { this.rowd = rowd; this.cold = cold; }
    public Dir next() { return values()[(ordinal()+1) % values().length]; }
  }
  static final int rows = 4, cols = 6;
  static final int[][] grid = new int[rows][cols];
  static int row, col = -1, step;

  public static void main(String[] args) {
    Dir dir = Dir.R;
    moving: while (true) {
      for (int i = 0; i < Dir.values().length; i++, dir = dir.next())
        if (move(dir)) continue moving;
      break;
    }
    for (int[] row : grid) System.out.println(Arrays.toString(row));
  }
  static boolean move(Dir dir) {
    final int newRow = row+dir.rowd, newCol = col+dir.cold;
    if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols
        && grid[newRow][newCol] == 0)
    {
      row = newRow; col = newCol; grid[row][col] = ++step; return true;
    }
    return false;
  }
}

Square Spiral 方螺旋

Here is a compact solution in a single function that performs optimally (it only visits each location in the array exactly once): 这里是在执行最佳的单一功能的紧凑的解决方案(它仅在数组中访问的每个位置正好一次):

static int anMoveXDir[] = { 1, 0, -1,  0 };
static int anMoveYDir[] = { 0, 1,  0, -1 };

static void DoSpiral(int *panGrid, int nWidth, int nHeight)
{
    int nSideSel, nSideIdx, nMoveDir, nXPosn, nYPosn, nCounter;
    int anSideLen[2];

    anSideLen[0] = nWidth;
    anSideLen[1] = nHeight - 1;

    nMoveDir = 0;     /* start off at (0, 0) in array, */
    nXPosn   = 0;     /* facing east, and count from 1 */
    nYPosn   = 0;
    nCounter = 1;

    for (nSideSel = 0; anSideLen[nSideSel & 1]; anSideLen[nSideSel++ & 1]--)
        for (nSideIdx = anSideLen[nSideSel & 1]; nSideIdx; nSideIdx--)
        {
            panGrid[(nYPosn * nWidth) + nXPosn] = nCounter++;

            if (nSideIdx == 1)
                nMoveDir = (nMoveDir + 1) & 3;

            nXPosn += anMoveXDir[nMoveDir];
            nYPosn += anMoveYDir[nMoveDir]; 
        }
}           

This algorithm works on the simple rule that given a rectangular or square array of width x and height y , then the walking the array to create a Square Spiral can be done using the following number of steps: 此算法适用于以下简单规则:给定宽度为x且高度为y的矩形或正方形数组,然后使用以下步骤即可遍历数组以创建正方形螺旋:

x + (y - 1) + (x - 1) + (y - 2) + (x - 2) + (y - 3) + (x - 3) + ... + 0

The function above simply follows the above sequence. 上面的函数仅遵循上述顺序。 It starts at the top-left of the array facing east, walks x steps, turns right 90 degrees, walks (y - 1) steps, turns right 90 degress, walks (x - 1) steps, etc. etc. until either x or y is zero, whichever comes first. 它从面向东方的数组的左上角开始,向x步走,向右转90度,向(y - 1)步走,向右转90度下降,向(x - 1)步走,依此类推,直到xy为零,以先到者为准。

You can test the function above by inserting it into the test program below: 您可以通过将其插入以下测试程序来测试上述功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define GRID_WIDTH    7
#define GRID_HEIGHT  11

void main()
{
    int nXPosn, nYPosn;
    int anGrid[GRID_WIDTH * GRID_HEIGHT];
    int *pnValue;

    DoSpiral(anGrid, GRID_WIDTH, GRID_HEIGHT);

    for (pnValue = anGrid, nYPosn = 0; nYPosn < GRID_HEIGHT; nYPosn++, printf("\n"))
        for (nXPosn = 0; nXPosn < GRID_WIDTH; printf("%4i", *pnValue++), nXPosn++);
}

The output will be as follows (for a 7x11 grid as indicated in the above program): 输出将如下所示(对于上述程序中指示的7x11网格):

 1   2   3   4   5   6   7
32  33  34  35  36  37   8
31  56  57  58  59  38   9
30  55  72  73  60  39  10
29  54  71  74  61  40  11
28  53  70  75  62  41  12
27  52  69  76  63  42  13
26  51  68  77  64  43  14
25  50  67  66  65  44  15
24  49  48  47  46  45  16
23  22  21  20  19  18  17

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 高效的数据结构和算法-自然序列 - Efficient Data structure and Algorithm - Natural Sequence 高效搜索表格式结构的行的算法 - Efficient algorithm for searching a row which a tabular structure 具有高效查询算法的层次结构数据结构 - Hierarchy data structure wih efficient query algorithm 需要一个有效的算法来实现String.replaceAll() - Need an efficient algorithm to implement String.replaceAll() 我该如何解决这个问题,如果有的话,什么样的算法适合解决它 - How can I solve this problem, and what kind of algorithm is the appropriate on if any to solve it 给定大的树结构,是否有一种有效的算法可以对树进行查询或过滤? - Given a large tree structure, is there an efficient algorithm to do querying or filtering on the tree? 我需要一个有效的算法和/或代码来建模系统的泊松分布 - I need an efficient algorithm and/or code for a modelling Poisson distribution of a system 不确定此问题需要哪种算法/什么数据结构(打印机队列问题) - Not sure what kind of algorithm this problem requires / what data structure (Printer Queue problem) 总线路由程序,我使用什么样的算法和数据结构? - Bus Route Program,What kind of algorithm and data-structure do I use? 遗传算法 - 我需要什么数据结构? - Genetic Algorithm - what data structure do I need?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM