蓝桥杯算法:打印图形——六芒星

【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一个六芒星,表示满足题意的图形。
【样例输入】
3
4
【样例输出】

蓝桥杯算法:打印图形——六芒星_第1张图片
蓝桥杯算法:打印图形——六芒星_第2张图片
【评测用例规模与约定】
对于所有评测用例,1 ≤ n ≤ 20。

总结:

第一次做图形题,做了蛮久,图形题有很多的方式去完成,它考验的是你能不能找到更简单的那一种方式.

我初看到这个图形,第一种想法是把这个六芒星当做六个小三角形来做,然后以某种规则排列一下,就能做出来,但是尝试了一下感觉太麻烦了。

然后我的第二种想法是,这个图形是对称图形,怎么能写出一半吗? 这样另一半想办法翻转一下就可以了。 尝试了一下,感觉也挺麻烦,逻辑很难捋。

第三种想法是把整个六芒星进行分块,第一块是最上面的三角形,第二块是中间部分,第三块是下面的三角形,然后用三个for循环找到其中的规律,感觉逻辑更清晰了点,但是还是挺麻烦。

第四种想法是我突然灵机一动,发现六芒星可以分为两个大的三角形,我就觉得,就是它了. 第一开始我的想法是先把一个大三角实现出来再说,另一个大三角再用for循环找找规律应该就能输出出来.

后来我发现,用一个for循环就可以解决这个问题.

我的想法是把对应的值都放到一个二维数组里,然后最后直接输出二维数组即可,空格直接隔过去.

我们需要先理解下面这些运算才可以.

首先这根6n-5的线是怎么来的?
从上面的图可以看到,这根线由三个边长为n的三角形的边长组成. 所以应该是3n,但是因为中间那个三角形有两个点被覆盖了,所以需要减2. 就是 3n - 2.
这是这条线上所有的星星的数量,但是它的星星的排列是一个星星一个空格的形式,所以我们还得把空格计算出来.
我们可以看到左边,中间,右边三个三角形的空格数量都是n - 1,加一起就是3n - 3
所有加一块就是6n - 5 这样我们就得到这个边长的length了.

知道这个之后,我们就可以求得middleDot的位置,6n - 5一定是一个奇数,所以我们需要考虑这种情况——
middleDot = (6n - 5 ) / 2 = 3n - 5 / 2. 这里有一个小数,而int类型会直接把小数抹去,但是我们需要的是进一,所以需要加一.
middleDot = (6n - 5) / 2 + 1 . 这样我们就知道middleDot的位置了.

接下来,我们需要一个for循环来打印出三角形. 但是一个问题在于,我们根本不知道我们要打印多少行?
for ( int i = 0; i < ???; i ++)
于是我们需要算出一个大三角形有多少行,通过上面的图形可以知道,一个大三角形等于三个三角形的高减去两行重叠的部分.
也就是3n - 2.
而整个六芒星的高度就是四个三角形减去三行重叠的部分,为4n - 3
蓝桥杯算法:打印图形——六芒星_第3张图片
接下来我们就可以写这个循环了
for ( int i = 0; i < 3n-2; i ++){

}

那么是怎么一个for循环把两个三角形输出出来的呢? 我们只要控制这个循环,当他把正三角形的所有行输出完之后,就会停止.
然后我们只需要同时输出第i行,以及4n - 3 - i - 1行(减1的原因是我们的计算结果是从自然数数起,但是计算机是从0数起)即可.
这样就能实现正三角的1 2 3 4 …行,倒三角的9 8 7 6 5 4… 行. 当正三角循环结束的时候,倒三角的循环也结束了.

蓝桥杯算法:打印图形——六芒星_第4张图片

import java.util.Scanner;

public class printStar {
     
	public static void main(String[] args) {
     
		// 输入一个数
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		// 创建一个行为大三角形边长,列为整个六芒星的高的一个二维数组
		String[][] arr = new String[4 * n - 3][6 * n - 5];
		int middleDot = (6 * n - 5) / 2 + 1;  // 获取中心点的位置
		int triangleLine = 3 * n - 2;  // 获取三角形有多少行
		boolean isEmpty = true;  // 控制星星和空格
		// 行从0开始,一直遍历到整个大三角形的结尾
		for (int i = 0; i < triangleLine; i++) {
     
			int flipTriangleLine = 4 * n - 3 - i - 1;  // 这个是倒三角形的行,默认为最后一行,然后不断递减.  
			arr[i][middleDot - i - 1] = "*";  // middleDot是自然数计算的,在数组里,需要减一. 减i是给正三角的左边赋值
			arr[i][middleDot + i - 1] = "*";  // +i是给正三角的右边星星赋值
			arr[flipTriangleLine][middleDot - i - 1] = "*";  // 是给倒三角的左边星星赋值
			arr[flipTriangleLine][middleDot + i - 1] = "*";  // 是给倒三角的右边星星赋值
			
			if(i == triangleLine - 1) {
       // 现在的情况是只有两条边,但是底边没有绘制,所以我们需要把底边绘制出来. 如果判断是最后一次循环了.
				isEmpty = true;  // 首先重置一下isEmpty. 因为我们可以看到,上面的图形中,最后一行的第一个和最后一个星星,我们已经处理过了,这个时候我们的第一个元素是空格,所以第一个需要跳过.
				// 这一点不懂的话,可以去看下面的图. 可以看我们真正要赋值的是哪一个部分.
				for (int j = middleDot - i; j <= middleDot + i - 2; j ++) {
     
					if(isEmpty) {
       // 如果为空,变成false,这样就能控制一个星星,一个空格.
						isEmpty = false;
					}else {
       // 如果为false,就给正三角和倒三角的对应位置变成星星,列都是一样的,只是行不一样. 然后再维护一下isEmpty.
						arr[i][j] = "*";
						arr[flipTriangleLine][j] = "*";
						isEmpty = true;
					}
				}
			}
		}
		
		// 输出遍历,把null值变成空格.
		for (String[] i : arr) {
     
			for (String j : i) {
     
				if(j == null) {
     
					System.out.print(" ");
				}else {
     
					System.out.print(j);
				}
			}
			System.out.println();
		}
	}
}

蓝桥杯算法:打印图形——六芒星_第5张图片

你可能感兴趣的:(算法与数据结构,算法,java)