题目来自剑指offer
题目:
思路:每次打印一个环
根据上图,打印环时,可以分为四步:
(1)打印1,只要环存在,就该行就可以打印。
(2)打印2,只要环有多行(有待打印的元素)时,才可以打印。
(3)打印3、当环有多行(和其一次行区分开)+有多列(有待打印的元素)时,才有可能打印该行
(4)打印4、当环有多列(和其一次列区分开)+有多行(有待打印的元素)时,才有可能打印该列
注意:对于 判断是否有待打印的元素 的条件,可以再for循环中包含,可以在if中少写一个判断。
代码:
#include <iostream> #include <iomanip> #include <assert.h> using namespace std; /* 函数功能:打印环 nStart:起点坐标(nStart,nStart) nEndRows:本次打印的最后一行 nEndCols:本次打印的最后一列*/ void PrintCircle(int** pArr,int nStart,int nEndRows,int nEndCols) { //从左到右打印一行 //打印条件:第一行肯定能打印,不用写if语句 //打印第nStart行,列区间由nStart到nCols for (int nCurCol = nStart;nCurCol <= nEndCols;nCurCol++) { cout<<pArr[nStart][nCurCol]<<" "; } //从上到下打印一列 //打印条件:终止行大于第起始行(此条件已经暗含在for循环中了,可以不写) //打印第nCols列,列区间由nStart + 1到nRows for (int nCurRow = nStart + 1;nCurRow <= nEndRows;nCurRow++) { cout<<pArr[nCurRow][nEndCols]<<" "; } //从右到左打印一行 //打印条件:待打印的环中的行必须超过两行 且 列超过两列 //满足条件:nEndCols > nStart : 要求被打印那一行必须有未打印的元素(此条件已经暗含在for循环中了,可以不写) //满足条件:nEndRows > nStart : 这是要和前一次打印的行区分开。 //打印第nRows行,列区间由nCols - 1到nStart if (nEndRows > nStart) { for (int nCurCol = nEndCols - 1;nCurCol >= nStart;nCurCol--) { cout<<pArr[nEndRows][nCurCol]<<" "; } } //从下到上打印一列 //打印条件:待打印的环中的行必须超过三行 且 列超过两列 //满足条件:nEndCols > nStart : 因为这是要和前一次打印的列区分开。 //满足条件:nEndRows > nStart : 要求被打印那一列必须有未打印的元素,(此条件已经暗含在for循环中了,可以不写)。 //打印第nStart列,行区间由nRows - 1到nStart + 1 if (nEndCols > nStart) { for (int nCurRow = nEndRows - 1;nCurRow >= nStart + 1;nCurRow--) { cout<<pArr[nCurRow][nStart]<<" "; } } } /* 函数功能:确定环的个数 nRows:表示总行数,nCols:表示总列数*/ void PrintMatrix(int** pArr,int nRows,int nCols) { assert(pArr && nCols > 0 && nRows > 0); int nStart = 0; while (2 * nStart < nRows && 2 * nStart < nCols) { PrintCircle(pArr,nStart,nRows - 1 - nStart,nCols - 1 - nStart); nStart++; } } int main() { int nRows = -1; int nCols = -1; int num = 1; cin>>nRows>>nCols; int** pArr = new int*[nRows]; for(int i = 0;i < nRows;i++) { pArr[i]= new int[nCols]; for(int j = 0;j < nCols;j++) { pArr[i][j]= num++; cout<<setw(3)<<pArr[i][j]<<" "; } cout<<endl; } cout<<endl; PrintMatrix(pArr,nRows,nCols); cout<<endl; system("pause"); return 1;
题目扩展
题目:产生螺旋数组
举例:
思路:与上面的思路是一样的,代码也几乎一样。
代码:
#include <iostream> #include <iomanip> #include <assert.h> using namespace std; /* 函数功能:打印环 nStart:起点坐标(nStart,nStart) nEndRows:本次打印的最后一行 nEndCols:本次打印的最后一列*/ void PrintCircle(int** pArr,int nStart,int nEndRows,int nEndCols,int& nCnt) { //从左到右打印一行 //打印条件:第一行肯定能打印,不用写if语句 //打印第nStart行,列区间由nStart到nCols for (int nCurCol = nStart;nCurCol <= nEndCols;nCurCol++) { pArr[nStart][nCurCol] = nCnt++; } //从上到下打印一列 //打印条件:终止行大于第起始行(此条件已经暗含在for循环中了,可以不写) //打印第nCols列,列区间由nStart + 1到nRows for (int nCurRow = nStart + 1;nCurRow <= nEndRows;nCurRow++) { pArr[nCurRow][nEndCols]= nCnt++; } //从右到左打印一行 //打印条件:待打印的环中的行必须超过两行 且 列超过两列 //满足条件:nEndCols > nStart : 要求被打印那一行必须有未打印的元素(此条件已经暗含在for循环中了,可以不写) //满足条件:nEndRows > nStart : 这是要和前一次打印的行区分开。 //打印第nRows行,列区间由nCols - 1到nStart if (nEndRows > nStart) { for (int nCurCol = nEndCols - 1;nCurCol >= nStart;nCurCol--) { pArr[nEndRows][nCurCol]= nCnt++; } } //从下到上打印一列 //打印条件:待打印的环中的行必须超过三行 且 列超过两列 //满足条件:nEndCols > nStart : 因为这是要和前一次打印的列区分开。 //满足条件:nEndRows > nStart : 要求被打印那一列必须有未打印的元素,(此条件已经暗含在for循环中了,可以不写)。 //打印第nStart列,行区间由nRows - 1到nStart + 1 if (nEndCols > nStart) { for (int nCurRow = nEndRows - 1;nCurRow >= nStart + 1;nCurRow--) { pArr[nCurRow][nStart]= nCnt++; } } } /* 函数功能:确定环的个数 nRows:表示总函数,nCols:表示总列数*/ void PrintMatrix(int** pArr,int nRows,int nCols) { assert(pArr && nCols > 0 && nRows > 0); int nStart = 0; int nCnt = 1; while (2 * nStart < nRows && 2 * nStart < nCols) { PrintCircle(pArr,nStart,nRows - 1 - nStart,nCols - 1 - nStart,nCnt); nStart++; } } int main() { int nRows = -1; int nCols = -1; int num = 1; cin>>nRows>>nCols; //产生二维数组 int** pArr = new int*[nRows]; for(int i = 0;i < nRows;i++) { pArr[i]= new int[nCols]; } //打印 PrintMatrix(pArr,nRows,nCols); //输出 for(int i = 0;i < nRows;i++) { for(int j = 0;j < nCols;j++) { cout<<setw(3)<<pArr[i][j]<<" "; } cout<<endl; } system("pause"); return 1; }