[英]Need an efficient algorithm solve this kind of complex structure
問題陳述是:
給定2維數組,例如打印輸出
如果是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
我試過它看起來像正方形在正方形內,但是當我嘗試這個問題時,我放了很多while和if循環,但沒有確切的答案。 如果行和列增加了怎么處理呢?
這不是功課。 我正在學習解決復雜的結構,因此我需要通過一些指導來理解它。
這是一個方形螺旋。
您可以在此處閱讀有關它的內容: http : //metacpan.org/pod/Math :: PlanePath :: SquareSpiral
公式有一個解釋。
這是我附帶的東西。
變量名稱可能上下顛倒,很多事情需要增強,刪除,修改,但這很有趣。
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("");
}
}
使用相同的“螺旋行走”算法的另一種解決方案:
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));
}
}
我希望這個想法可以幫助您入門:
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
// ...
// ...
}
我可能會創建一個NxM整數數組,初始化為零。 將nextNumber
設置為1,將position
為0,0,將direction
設置left-to-right
。 檢查position
是否在數組之外,並檢查position
為零的單元格。 如果position
確定並且單元格為零,則在其中存儲nextNumber
並遞增nextNumber
。 然后,根據direction
,增加position
。
如果position
的像元非零,或者position
的索引之一為<0或> =數組大小,則需要更改方向。 首先使用現有方向將position
備份1。 然后選擇一個與當前值成90度的新direction
,增加position
,然后重試。
當您無法完成任何方向時,請打印陣列。
(上面我可能會處理一些邊界條件,但這是一個基本算法。)
(提示:編寫一個子程序以根據direction
增加/減少position
。)
我想您可以創建一條蠕蟲傳播通過您的陣列:
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;
}
}
是的,我的蠕蟲朝着另一個方向傳播,因為我希望您也多想一點並了解我在做什么。 因為我認為這是家庭作業。 (如果是這樣,您是否可以考慮在問題中添加“作業”標簽?)
編輯:哎呀,不完全是,它應該做什么。 現在沒有時間,將在晚上進行調查。
另取:
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;
}
}
方螺旋
這里是在執行最佳的單一功能的緊湊的解決方案(它僅在數組中訪問的每個位置正好一次):
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];
}
}
此算法適用於以下簡單規則:給定寬度為x
且高度為y
的矩形或正方形數組,然后使用以下步驟即可遍歷數組以創建正方形螺旋:
x + (y - 1) + (x - 1) + (y - 2) + (x - 2) + (y - 3) + (x - 3) + ... + 0
上面的函數僅遵循上述順序。 它從面向東方的數組的左上角開始,向x
步走,向右轉90度,向(y - 1)
步走,向右轉90度下降,向(x - 1)
步走,依此類推,直到x
或y
為零,以先到者為准。
您可以通過將其插入以下測試程序來測試上述功能:
#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++);
}
輸出將如下所示(對於上述程序中指示的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.