题目描述
给定一个row行col列的整数数组array,要求从array[o][0]元素开始,按从左上到右下的对角线顺序遍历整个数组。
关于输入
输入的第一行上有两个整数,依次为row和col。余下有row行,每行包含col个整数,构成一个二维整数数组。
(注:输入的row和col保证0<row<100, 0<col<100)关于输出按遍历顺序输出每个整数。每个整数占一行。
例子输入1:
3 4
1 2 4 7
3 5 8 10
6 9 11 12
例子输出1:
1
2
3
4
5
6
7
8
9
10
11
12
例子输入2:
4 5
1 2 4 7 11
3 5 8 12 15
6 9 13 16 18
10 14 17 19 20
例子输出2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
解法一:拟人法
将需要实现的部分分成两部分:
1 找到合适的起点;
2 由起点开始,向左下方向遍历数组。
#include<stdio.h>
int a[100][100];
int ROW;
void biu( int a[100][100],int col,int row){//向左下方向遍历数组,遇底边界或左边界停止
while(col>=0 && row<ROW){
printf("%d\n",a[row][col]);
col--;
row++;
}
}
main(){
int COL;
scanf("%d %d",&ROW,&COL);//设置长宽
for(int i=0;i<ROW;i++){//输入二维数组数据
for(int j=0;j<COL;j++){
scanf("%d",&(a[i][j]));
}
}
int row=0,col=0;
do{
biu(a,col,row);
col++;
}while(col<COL-1);
do{
biu(a,col,row);
row++;
}while(row<ROW);
}
其中,自定义的“biu"函数实现上述第二个部分(由起点开始,向左下方向遍历数组),并能遇底边界或左边界停止。
通过两个do-while循环结构实现起点由顶边到右侧边依次移动。起点移动过程如下图:
解法二:函数法/定值法
观察可得,遍历的每斜行row与col之和为定值(row+col=k)。即row=-col+k,整数函数。
但是,所给的数表并不一定为正方形。如何控制好边界是难点。
先放大范围,找出长边(“max”),将范围扩大至边长为max的正方形数表。
而按照和为定值的方式遍历难免再次放大范围,将范围扩大为了正方形数表面积两倍的三角形。
那么如何缩小范围呢?
在输出时加入了输出模块,该模块会将数的坐标位置与原数表范围作比较,以此筛去无用数字。
输出有效的数字,实现功能。
#include<stdio.h>
main(){
int ROW,COL;
int a[100][100];
scanf("%d %d",&ROW,&COL);//设置长宽
for(int i=0;i<ROW;i++){//输入二维数组数据
for(int j=0;j<COL;j++){
scanf("%d",&(a[i][j]));
}
}
//找出最大值
int max;
if(ROW>=COL) max=ROW;
else max=COL;
int col,row;
for(int i=0;i<2*max;i++){//找出正方形数组的右下顶点的col与row的和,并遍历和
for(row=0;row<max;row++){//以长宽中最大的一边为边长遍历正方形数组
col=i-row;//col边由和减row边算出
if(0<=row && row<ROW && col<COL && 0<=col){//输出模块;确保输出的数在范围内(即把正方形数组裁成长方形)
printf("%d\n",a[row][col]);
}
}
}
}
解法三:数学加权法
所谓遍历,讲究一个先后顺序;那么就要给数表中的数排序。我们进行一个从小到大排序。
右侧比左侧的值更晚输出,赋予更大的权。(1)
下面比上面的数更晚输出,赋予更大的权。(2)
那么右上和左下的比较呢?左下的数更晚出现!符合(2)规律,违背(1)规律。
所以向下的加权(2)要大于向右的加权(1)。
加权的实现通过简单的乘实现,向下的加权乘11,向右的加权乘10。某位置最后的权由纵向位置乘11加横向位置乘10所得,为所有数排上了不连续,但大小特征正确的序。
不采用小数加权是为了构建整数总权。因为只有整数型的总权才可以作为数组地址使用。
在输入数表的同时,程序就直接把数字存到总权值对应的地址的“num”数组中。
由于这些权不是连续分布,数字也不是在“num”数组中连续分布。故设计“index”数组辅助,“index”数组不记录具体数字,仅记录有无(有为1,无为0)。“index”数组的地址与“num”数组相同,都是数字的总权。
有了“index”数组的帮助,加以“过滤输出”(与方法二中类似),实现。
#include<stdio.h>
main(){
int ROW,COL,site;
int a[100][100];
int index[10000]={0};
int num[10000];
scanf("%d %d",&ROW,&COL);//设置长宽
int max;//算出最小的可以框住矩形数表的正方形数表的边长,即两边中较大的一边
if(ROW>=COL) max=ROW;
else max=COL;
for(int y=1;y<=ROW;y++){//
for(int x=1;x<=COL;x++){
site=x*10+y*11;//加权后的数值也是位置的体现
index[site]=1;//将索引列表中相应位置开关打开
scanf("%d",&num[site]);//将数直接存到一维列表中,与索引位置对应
}
}
for(int i=21;i<21*max;i++){
if(index[i]==1){//通过索引开关过滤
printf("%d\n",num[i]);
}
}
}