蓝桥杯 回形取数(Java)

1.题目描述

回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入
输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出
输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3
1 2 3
4 5 6
7 8 9
样例输出
1 4 7 8 9 6 3 2 5

2.思路

取数方向相当于 下–>右–>上–>左
所以可以编写四个方向的函数(down,right,up,left)对此进行操作,再写一个总的方法(take)来调用四个子方法,每次需要判断到底是哪个方向上的坐标不变,将输出过的那个坐标上的数改为0,我们就能知道它已经被遍历过了。
但是最后提交时还是不对,73分,看测试数据的时候他也没给我到底哪不对,所以暂时还没真正的做出来,也不知道到底哪错了,希望有热心大佬指出一下
代码:

import java.util.Scanner;
public class ReturnShapeTaking {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt();
		int b = sc.nextInt();
		int[][] m = new int[a][b];
		for(int i = 0; i < a; ++i) {
			for(int j = 0; j < b; ++j) {
				m[i][j] = sc.nextInt();
			}
		}
		take(m,a,b);
	}
	private static void take(int[][] m, int a, int b) {
		//相当于逆时针取数:下--》右--》上--》左
		//判断a,b大小,防止行列大小不同时,出现数组下标越界异常
		if(a >= b) {
			for(int j = 0; j < b; ++j) {
				down(m,j);
				right(m,a - j - 1);
				up(m,b - j - 1);
				left(m,j);
			}
		} else if(a <= b) {
			for(int j = 0; j < a; ++j) {
				down(m,j);
				right(m,a - j - 1);
				up(m,b - j - 1);
				left(m,j);
			}
		}
	}
	public static void down(int[][] m, int j) {//列不变,行在变
		for(int i = 0; i < m.length; ++i) {
			if(m[i][j] != 0) {
				System.out.print(m[i][j] + " ");
                m[i][j] = 0;	
			}
		}
	}
	
	public static void right(int[][] m, int i) {//行不变,列在变
		for(int j = 0; j < m[0].length ; ++j) {
			if(m[i][j] != 0) {
				System.out.print(m[i][j] + " ");
                m[i][j] = 0;	
			}
		}
	}
	public static void up(int[][] m, int j) {//列不变,行在变
		for(int i = m.length - 1; i >= 0; --i) {
			if(m[i][j] != 0) {
				System.out.print(m[i][j] + " ");
                m[i][j] = 0;	
			}
		}
	}
	public static void left(int[][] m, int i) {//行不变,列在变
		for(int j = m[i].length - 1; j >=0; --j) {
			if(m[i][j] != 0) {
				System.out.print(m[i][j] + " ");
                m[i][j] = 0;	
			}
		}
	}
}

另外,需要注意的是

System.out.println("*****"+m[0].length);//表示m[0]这列的长度
System.out.println("======"+m.length);//表示行的长度,之前忽视了这个问题

3.正确解法

然后老规矩,搜大佬写的来看
链接:link转载解法.
思路:(转载上文)
1.首先,每一轮开始的坐标x,y都相同,开始为0,后续每轮加一。我们发现循环打印的条件是columns>startX2&&rows>startY2.
2.打印可能有四步,向右,向下,向左,向上。但并不是每次都如此,因此我们要分析具体条件。(1)第一步向右总是需要的(2)当终止行号大于起始行号,也就是至少要两行,才有第二步向下。(3)至少有两行之后,还要至少两列才有第三步向左。(4)有两列的情况下,当至少有三行才有第四步向上。
这个已经说得很清楚了,然后自己再debug几个示例。后面自己敲了一遍,改成了这道题的要求,原文输出顺序略有差异。

import java.util.Scanner;

public class ReturnShapeTaking_2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt();
		int b = sc.nextInt();
		int[][] m = new int[a][b];
		for(int i = 0; i < a; ++i) {
			for(int j = 0; j < b; ++j) {
				m[i][j] = sc.nextInt();
			}
		}
		sc.close();
		take(m,a,b);
	}

	private static void take(int[][] m, int a, int b) {
		if (m==null||a<=0||b<=0)
            return;
		int start = 0;
		while(a > start * 2 && b > start * 2) {
		//start一次打印结束后,start需要后移,如果行列有一个小于start*2就意味着已经打印完了,
		//因为一次循环打印可以处理两行两列。这个控制个人感觉还是特别巧妙,做题的时候想不到
			printNum(m,a,b,start);
			start++;
		}
	}
	private static void printNum(int[][] m, int a, int b, int start) {
		int endX = a - start - 1;//x横坐标与行有关
		int endY = b - start - 1;
		//第一次必须向下打印(因为会出现最后只剩一列的时候)
		for(int i = start; i <= endX; ++i) {
			System.out.print(m[i][start] + " ");
		}
		//向右打印,但是要判断是否还需要向右打印
		if(start < endY) {
			for(int i = start + 1; i <= endY; ++i) {
				System.out.print(m[endX][i] + " ");
			}
		}
		//向上打印,但是要判断是否还需要向上打印
				if(start < endX && start < endY) {
					for(int i = endX - 1; i >= start; --i) {
						System.out.print(m[i][endY] + " ");
					}
				}
		//向左打印,但是要判断是否还需要向左打印
		if(start < endY && start < endX) {
			for(int i = endY - 1; i > start; --i) {
				System.out.print(m[start][i] + " ");
			}
		}
	}
}

自己有些细节没把握好,打印的数到底和横纵坐标哪个有关,打印循环的条件是大于start而不是大于0,等……背着写一遍之后找错找安逸了。。。。。疯狂举例debug

学习心得:应该是二维数组这块的基础没有打牢,把自己绕晕了,真惨。一页多的提交记录。

蓝桥杯是中国最具影响力的计算机竞赛之一,回形取数蓝桥杯中的一道经典题目。下面是关于Python实现回形取数的介绍: 回形取数是指从一个矩阵中按照回形的方式依次取出所有的元素。具体来说,就是从矩阵的左上角开始,按照顺时针的方向依次取出元素,直到取完所有元素为止。 在Python中,可以通过嵌套列表来表示矩阵。下面是一个示例代码,实现了回形取数的功能: ```python def spiral_order(matrix): if not matrix: return [] rows, cols = len(matrix), len(matrix[0]) top, bottom, left, right = 0, rows - 1, 0, cols - 1 result = [] while top <= bottom and left <= right: # 从左到右 for col in range(left, right + 1): result.append(matrix[top][col]) top += 1 # 从上到下 for row in range(top, bottom + 1): result.append(matrix[row][right]) right -= 1 if top <= bottom: # 从右到左 for col in range(right, left - 1, -1): result.append(matrix[bottom][col]) bottom -= 1 if left <= right: # 从下到上 for row in range(bottom, top - 1, -1): result.append(matrix[row][left]) left += 1 return result # 测试 matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] result = spiral_order(matrix) print(result) ``` 以上代码中,`spiral_order`函数接受一个二维列表作为输入,表示矩阵。函数通过设定上下左右四个边界来控制取数的范围,然后按照顺时针的方向依次取出元素,并将其添加到结果列表中。最后返回结果列表。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值