打印沙漏-算法

打印沙漏

题目

顾名思义,就是要输出一个沙漏,那么什么是沙漏呢,就是下面的样子了

  *****
   ***
    *
   ***
  *****

也就是要给我们n个*,这个沙漏每一行的 符号 数量都是奇数,因此是有规律的。

输入例子

19 //多少个符号 *

输出例子

  //打印出一个沙漏
  *****
   ***
    *
   ***
  ***** 
  2 //剩余没有用掉的符号数量

解题思路

这个解题思路是我在网上看到的,他把这个沙漏 具像化,*号用坐标来显示,那么上面的例子就是

  (0,0)(0,1)(0,2)(0,3)(0,4)
         (1,1)(1,2)(1,3)
                (2,2)
         (3,1)(3,2)(3,3)
  (4,0)(4,1)(4,2)(4,3)(4,4)

这样的话,继续观察一下,发现他可以上下对折,左右对折变成下面这样

  (0,0)(0,1)(0,2)
         (1,1)(1,2)
                (2,2)

发现了什么,列 >= 行,然后接下来左右对称,上下对称

  当 行坐标 > 行数 / 2 也就是过半的时候, 这时的行坐标 = 总行数 - 当前行数 - 1,比如下一行 行坐标 3 = 5 - 3 -1 = 1 所以 行坐标 3 的行和行坐标 1 的行对称。

列也是一样 因为列数 = 行数 所以

  当 列坐标 > 行数 / 2 也就是过半的时候, 这时的列坐标 = 总行数 - 当前列数 - 1,比如下一列 列坐标 3 = 5 - 3 - 1 = 1 所以列坐标 3 的列和列坐标 1 的列对称。

当然了,中间那一行(列)没有对称

代码

下面是 我用 php 实现的代码,任何语言都大同小异。

<?php
  function test($count, $symbol)
    {
        $maxRow = 1; //最大行 即 最小行
        $maxCount = 1; //最大个数 即 最小个数
        //先判断 数量 如果是小于 最小个数 那么输出 数量
        if ($count < $maxCount) {
            printf($count);
        } else {
            //循环 算出 最大行数 统计最大个数 后面用来算剩余个数
            while (true) {
                //可以输出
                //下一行的数量 = 之前的数量 + 下一行所需的数量((行数 + 2) 是下一行的数量,但是沙漏需要上下两行,所以 * 2)
                $nextCount = ($maxRow + 2) * 2 + $maxCount;
                //判断不够了 结束
                if ($count < $nextCount) {
                    break;
                } elseif ($count == $nextCount) {
                    //刚好够 数量增加 行增加
                    $maxRow += 2;
                    $maxCount = $nextCount;
                    break;
                } else {
                    //完全够 数量增加 行增加 然后继续循环
                    $maxRow += 2;
                    $maxCount = $nextCount;
                }

            }
            //开始输出
            for ($i = 0; $i < $maxRow; $i++) {
                //循环所有行
                $row = $i; //当前行
                //判断 当前行 到一半了,那么把行数倒过来,让它向上跑
                if ($i > $maxRow / 2) {
                    $row = $maxRow - $row - 1;
                }
                for ($j = 0; $j < $maxRow; $j++) {
                    //循环所有列
                    $col = $j;
                    //列和行一样 做个判断
                    if ($col > $maxRow / 2) {
                        $col = $maxRow - $col - 1;
                    }
                    //如果 当前列 < 当前行
                    if ($col < $row) {
                        //如果 到了 最后 就要换行 在 前面 则输出 空格
                        if ($j > $maxRow / 2) {
                            printf("\n");
                            break;
                        } else {
                            printf(" ");
                        }

                    } else {
                        //列 > 行 直接输出 符号
                        printf($symbol);
                    }
                    //输出完 最后一个符号后 换行 当列 = 最后一行的时候
                    if ($j == $maxRow - 1) {
                        printf("\n");
                    }
                }
            }
            //输出 剩余的 符号数量
            printf($count - $maxCount);
        }

    }

参考资料

我只是略作更改,最小使用1个*,和一些变量使用上的微调 下面原文c语言的链接

https://blog.csdn.net/hcy2319964421/article/details/53103641

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值