一、题目描述
Day8:寻路算法---深度寻路__Brooke_的博客-CSDN博客
个人的原始解法:类似于上面的博客所解(就是比较费空间)下面着重介绍一下"循环不变量"
class Solution { public: typedef struct Pos { int x; int y; }Pos;//记录坐标 enum dir { right = 0, down, left, up }; bool Check(bool** Map, Pos CurPos, int CurDir, int n)//判断是否需要改变的方向的 { if (CurDir == 0)//向右的 {//检测右边是否为边界or已经走过的地方 if (CurPos.x + 1 >= n || Map[CurPos.x + 1][CurPos.y] == 1)//短路特性 { return true;//说明需要改变方向 } } if (CurDir == 1)//向下的 {//检测右边是否为边界or已经走过的地方 if (CurPos.y + 1 >= n || Map[CurPos.x][CurPos.y + 1] == 1)//短路特性 { return true;//说明需要改变方向 } } if (CurDir == 2)//向左的 {//检测右边是否为边界or已经走过的地方 if (CurPos.x - 1 <0 || Map[CurPos.x - 1][CurPos.y] == 1)//短路特性 { return true;//说明需要改变方向 } } if (CurDir == 3)//向上的 {//检测右边是否为边界or已经走过的地方 if (CurPos.y - 1 <0 || Map[CurPos.x][CurPos.y - 1] == 1)//短路特性 { return true;//说明需要改变方向 } } return 0; } void move(int CurrentDir, Pos& CurrentPos) { if (CurrentDir == 0)//向右的 { CurrentPos.x += 1; } if (CurrentDir == 1)//向下的 { CurrentPos.y += 1; } if (CurrentDir == 2)//向左的 { CurrentPos.x -= 1; } if (CurrentDir == 3)//向上的 { CurrentPos.y -= 1; } } vector<vector<int>> generateMatrix(int n) { if(n!=1) { Pos CurrentPos = { 0,0 };//起始坐标 //观察图像易知,行走的顺序始终都是按照这样的变化规律的 //向左or向右的运动--仅仅只是改变横坐标,当向上or向下的时候--改变n(物理存储上) int CurrentDir = 0;//默认从向右走起 int** res = new int* [n];//全部置为0,表示没有走过 for (int i = 0; i < n; i++) { res[i] = new int[n] {0};//错误2 } bool** FlagMap = new bool* [n];//全部置为0,表示没有走过 for (int i = 0; i < n; i++) { FlagMap[i] = new bool[n]{0};//错误4 } FlagMap[CurrentPos.x][CurrentPos.y] = 1;//起点先标记走过 for (int i = 0; i < n * n; i++)//一共操作n²次 { if (Check(FlagMap, CurrentPos, CurrentDir, n)) {//看是否要改变方向 CurrentDir = (CurrentDir + 1) % 4;//不能超过4 } //放入对应位置的数组 res[CurrentPos.x][CurrentPos.y] = (i+1);//错误5:前后两者的顺序 //走到下一个要插入的位置 move(CurrentDir, CurrentPos); //flagmap对应位置需要标记走过 FlagMap[CurrentPos.x][CurrentPos.y] = 1; } vector<vector<int>> Res; for (int i = 0; i < n; i++) { vector<int>tmp; Res.push_back(tmp);//错误三 for (int j = 0; j < n; j++) { Res[i].push_back(res[j][i]); } } for (int i = 0; i < n; i++) { delete[] res[i]; } delete[]res; for (int i = 0; i < n; i++) { delete[]FlagMap[i]; } delete[]FlagMap; return Res; } else { vector<vector<int>> res; vector<int> vec; vec.push_back(1); res.push_back(vec); return res; } vector<vector<int>> res; return res; } };
注意:
①用new来申请二维数组的时候,在对每一行开辟内存的时候,一定要记得切换。res[i]
②vector<vector<int>> res只是声明有这样一个类型,在做具体int类型数据的插入的时候,一定要先插入一个vector<int>进去
③报错 :.Runtime error: load of value 127, which is not a valid value for type 'bool'
原因:在开辟bool类型的二维数组的时候,并没有给其初始化,导致此error
二、循环不变量解法
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。
一些同学做这道题目之所以一直写不好,代码越写越乱。就是因为在画每一条边的时候,一会左开右闭,一会左闭右闭,一会又来左闭右开,岂能不乱。
代码如下,已经详细注释了每一步的目的,可以看出while循环里判断的情况是很多的,代码里处理的原则也是统一的左闭右开。
class Solution { public: vector<vector<int>> generateMatrix(int n) { vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组 int startx = 0, starty = 0; // 定义每循环一个圈的起始位置 int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) int count = 1; // 用来给矩阵中每一个空格赋值 int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位 int i,j; while (loop --) { i = startx; j = starty; // 下面开始的四个for就是模拟转了一圈 // 模拟填充上行从左到右(左闭右开) for (j = starty; j < n - offset; j++) { res[startx][j] = count++; } // 模拟填充右列从上到下(左闭右开) for (i = startx; i < n - offset; i++) { res[i][j] = count++; } // 模拟填充下行从右到左(左闭右开) for (; j > starty; j--) { res[i][j] = count++; } // 模拟填充左列从下到上(左闭右开) for (; i > startx; i--) { res[i][j] = count++; } // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) startx++; starty++; // offset 控制每一圈里每一条边遍历的长度 offset += 1; } // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 if (n % 2) { res[mid][mid] = count; } return res; } };
注意:
①循环圈数是n/2,如果是奇数,会留下最后一个mid点,判断一下赋值即可
②offset控制每次均为左闭右开
其他解法:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int t = 0; // top
int b = n-1; // bottom
int l = 0; // left
int r = n-1; // right
vector<vector<int>> ans(n,vector<int>(n));
int k=1;
while(k<=n*n){
for(int i=l;i<=r;++i,++k) ans[t][i] = k;
++t;
for(int i=t;i<=b;++i,++k) ans[i][r] = k;
--r;
for(int i=r;i>=l;--i,++k) ans[b][i] = k;
--b;
for(int i=b;i>=t;--i,++k) ans[i][l] = k;
++l;
}
return ans;
}
};
类似题目
- 54.螺旋矩阵
- 剑指Offer 29.顺时针打印矩阵