《剑指offer》面试题:顺时针打印矩阵

来源:互联网 发布:2017网络上很火的神曲 编辑:程序博客网 时间:2024/04/30 15:06

题目和要求看下面的说明

/*题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.输入:输入可能包含多个测试样例,对于每个测试案例,输入的第一行包括两个整数m和n(1<=m,n<=1000):表示矩阵的维数为m行n列。接下来的m行,每行包括n个整数,表示矩阵的元素,其中每个元素a的取值范围为(1<=a<=10000)。输出:对应每个测试案例,输出一行,按照从外向里以顺时针的顺序依次打印出每一个数字,每个数字后面都有一个空格。样例输入:4 41 2 3 45 6 7 89 10 11 1213 14 15 16样例输出:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 */#include<stdio.h>#include<stdlib.h>//根据起点来按圈打印矩阵 void printMatrixByCircle(int **arr,int m,int n,int begin){    if(arr==NULL||m<=0||n<=0||begin<0){        return;    }    //先从起点开始向右打印    for(int i=begin;i<n-begin;i++){//边界为 n-begin         printf("%d ",arr[begin][i]);//行固定,arr[bigin][i]也可以这样写:*(*(arr+begin)+i)     }     //然后向下打印    for(int i=begin+1;i<m-begin;i++){//为避免重复打印,起点为begin+1;边界为:m-begin        printf("%d ",arr[i][n-begin-1]);//列固定     }     //然后向左打印;这里如果 循环中i>=begin这样写,则当我们输入3*4的矩阵时,则为把起点元素打印两次 。因此应该这样来改写:i>begin ,把i=begin的情况留给下面那一组     for(int i=n-begin-2;i>begin;i--){//为避免重复打印,起点为n-begin-2;终点边界为 begin         printf("%d ",arr[m-begin-1][i]);    }     //然后向上打印    for(int i=m-1-begin;i>begin;i--){//为避免重复打印,起点为m-begin-2;终点边界为 begin+1         printf("%d ",arr[i][begin]);    } }void printMatrixByClockwise(int **arr,int m,int n){    if(arr==NULL||m<=0||n<=0){        return;    }    int begin=0;//第一步是从左上角位置为起点的圆开始打印    while(m>2*begin&&n>2*begin){//只有当m、n都大于begin的两倍时,才会有圈出现         printMatrixByCircle(arr,m,n,begin);        begin++;     } }int main(void){    int m,n;    while(scanf("%d%d",&m,&n)!=EOF){        if(m>0&&n>0){            int **arr;            arr=(int **)malloc(m*sizeof(int *));            if(arr==NULL){                exit(EXIT_FAILURE);            }            int val;            for(int i=0;i<m;i++){                arr[i]=(int *)malloc(n*sizeof(int));                if(arr[i]==NULL){                    exit(EXIT_FAILURE);                }                for(int j=0;j<n;j++){                    scanf("%d",&val);                    arr[i][j]=val;                }            }            printMatrixByClockwise(arr,m,n);        }    }    return 0;}

上面编码的思路就是利用4个for循环对一个圈进行了打印。

在调试过程中,遇到了如下的问题:能够处理4*3和4*4这样的矩阵,但是在输入为3*4的矩阵时,本来应该不会执行向左打印,但是向左打印的代码中for(int i=n-begin-2;i>=begin;i--)是要被执行的。
即会将arr[1][1]的元素重复打印。
因此我们将如下代码中的两个for循环条件进行了变化。

for(int i=n-begin-2;i>=begin;i--){//为避免重复打印,起点为n-begin-2;终点边界为 begin         printf("%d ",arr[m-begin-1][i]);    }     //然后向上打印    for(int i=m-2-begin;i>begin;i--){//为避免重复打印,起点为m-begin-2;终点边界为 begin+1         printf("%d ",arr[i][begin]);    } 

变化的结果如下:

    //然后向左打印;这里如果 循环中i>=begin这样写,则当我们输入3*4的矩阵时,则为把起点元素打印两次 。因此应该这样来改写:i>begin ,把i=begin的情况留给下面那一组     for(int i=n-begin-2;i>begin;i--){//为避免重复打印,起点为n-begin-2;终点边界为 begin         printf("%d ",arr[m-begin-1][i]);    }     //然后向上打印    for(int i=m-1-begin;i>begin;i--){//为避免重复打印,起点为m-begin-2;终点边界为 begin+1         printf("%d ",arr[i][begin]);    } 

这样就能够将 类似3*4的矩阵正常打印了,但是这样改了之后当测试4*3的矩阵时,发现又有重复的元素被打印了

在类似4*3的矩阵中,按圈打印时的第二圈中,应该只会执行向右打印和向下打印,但是代码中向上打印被执行了。向上打印中for循环条件如下:

for(int i=m-1-begin;i>begin;i--)

这样就导致了a[2][1]的元素被打印出来了。

总结:向以上的问题就是代码不能够同时处理3*4和4*3这样的矩阵。因此我们在代码中加入一个判断语句即可解决以上两个问题的冲突。

完整代码如下:

/*题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.输入:输入可能包含多个测试样例,对于每个测试案例,输入的第一行包括两个整数m和n(1<=m,n<=1000):表示矩阵的维数为m行n列。接下来的m行,每行包括n个整数,表示矩阵的元素,其中每个元素a的取值范围为(1<=a<=10000)。输出:对应每个测试案例,输出一行,按照从外向里以顺时针的顺序依次打印出每一个数字,每个数字后面都有一个空格。样例输入:4 41 2 3 45 6 7 89 10 11 1213 14 15 16样例输出:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 */#include<stdio.h>#include<stdlib.h>//根据起点来按圈打印矩阵 void printMatrixByCircle(int **arr,int m,int n,int begin){    if(arr==NULL||m<=0||n<=0||begin<0){        return;    }    //先从起点开始向右打印    for(int i=begin;i<n-begin;i++){//边界为 n-begin         printf("%d ",arr[begin][i]);//行固定,arr[bigin][i]也可以这样写:*(*(arr+begin)+i)     }     //然后向下打印    for(int i=begin+1;i<m-begin;i++){//为避免重复打印,起点为begin+1;边界为:m-begin        printf("%d ",arr[i][n-begin-1]);//列固定     }     //然后向左打印;这里如果 循环中i>=begin这样写,则当我们输入3*4的矩阵时,则为把起点元素打印两次 。因此应该这样来改写:i>begin ,把i=begin的情况留给下面那一组     if(m>=n){        for(int i=n-begin-2;i>=begin;i--){//为避免重复打印,起点为n-begin-2;终点边界为 begin             printf("%d ",arr[m-begin-1][i]);        }         //然后向上打印        //当输入4*3的矩阵时,会将a[2][1] 的元素重复打印         for(int i=m-2-begin;i>begin;i--){//为避免重复打印,起点为m-begin-2;终点边界为 begin+1             printf("%d ",arr[i][begin]);        }     }    if(m<n) {        for(int i=n-begin-2;i>begin;i--){//为避免重复打印,起点为n-begin-2;终点边界为 begin             printf("%d ",arr[m-begin-1][i]);        }         //然后向上打印        //当输入4*3的矩阵时,会将a[2][1] 的元素重复打印         for(int i=m-1-begin;i>begin;i--){//为避免重复打印,起点为m-begin-2;终点边界为 begin+1             printf("%d ",arr[i][begin]);        }     }}void printMatrixByClockwise(int **arr,int m,int n){    if(arr==NULL||m<=0||n<=0){        return;    }    int begin=0;//第一步是从左上角位置为起点的圆开始打印    while(m>2*begin&&n>2*begin){//只有当m、n都大于begin的两倍时,才会有圈出现         printMatrixByCircle(arr,m,n,begin);        begin++;     } }int main(void){    int m,n;    while(scanf("%d%d",&m,&n)!=EOF){        if(m>0&&n>0){            int **arr;            arr=(int **)malloc(m*sizeof(int *));            if(arr==NULL){                exit(EXIT_FAILURE);            }            int val;            for(int i=0;i<m;i++){                arr[i]=(int *)malloc(n*sizeof(int));                if(arr[i]==NULL){                    exit(EXIT_FAILURE);                }                for(int j=0;j<n;j++){                    scanf("%d",&val);                    arr[i][j]=val;                }            }            printMatrixByClockwise(arr,m,n);        }    }    return 0;}
0 0
原创粉丝点击