首页 > 其他分享 >使用打表法找规律

使用打表法找规律

时间:2022-09-02 22:25:21浏览次数:86  
标签:打表法 最少 当有 袋子 苹果 使用 堆草 true 规律

使用打表法找规律

作者:Grey

原文地址:

博客园:使用打表法找规律

CSDN:使用打表法找规律

打表法的使用条件

打表法适合:输入简单,输出也简单(只有一个数),可以暴力把一部分结果打印出来找规律,看下能否找到一个公式来优化代码。

买苹果问题

题目描述见:牛客:买苹果

暴力解法思路

  1. 如果是奇数,直接返回 -1,因为 6 和 8 不可能组成奇数

  2. 假设有 n 个苹果,最多需要n/8个 8 号袋,假设n/8=m,如果m==0,则最少需要m个 8 号袋子即可,如果m!=0,则看剩下的苹果能否被 被 6 号袋子消化,如果不能消化,则则减少一个 8 号袋子(m--),继续看剩下能否被 6 号袋搞定。

暴力解法的代码如下

    public static int minBags(int n) {
        if ((n & 1) == 1) {
            return -1;
        }

        if (n % 8 == 0) {
            // 全部可以被 8 号袋子分解
            return n / 8;
        }
        int use8 = n / 8;
        int rest = n % 8;
        while (rest != 0) {
            if (rest % 6 == 0) {
                // 分配了 8 号袋子,剩下的分配 6 号袋子,正好分配完。
                return use8 + (rest / 6);
            } else {
                // 分配了 8 号袋子,剩下的分配 6 号袋子,无法分配完,则减少一个 8 号袋子
                if (use8 > 0) {
                    use8--;
                    rest += 8;
                } else {
                    return -1;
                }
            }
        }
        return -1;
    }

打印出前几项的结果观察一下

当有0个苹果的时候,最少需要:0个袋子
当有1个苹果的时候,最少需要:-1个袋子
当有2个苹果的时候,最少需要:-1个袋子
当有3个苹果的时候,最少需要:-1个袋子
当有4个苹果的时候,最少需要:-1个袋子
当有5个苹果的时候,最少需要:-1个袋子
当有6个苹果的时候,最少需要:1个袋子
当有7个苹果的时候,最少需要:-1个袋子
当有8个苹果的时候,最少需要:1个袋子
当有9个苹果的时候,最少需要:-1个袋子
当有10个苹果的时候,最少需要:-1个袋子
当有11个苹果的时候,最少需要:-1个袋子
当有12个苹果的时候,最少需要:2个袋子
当有13个苹果的时候,最少需要:-1个袋子
当有14个苹果的时候,最少需要:2个袋子
当有15个苹果的时候,最少需要:-1个袋子
当有16个苹果的时候,最少需要:2个袋子
当有17个苹果的时候,最少需要:-1个袋子
当有18个苹果的时候,最少需要:3个袋子
当有19个苹果的时候,最少需要:-1个袋子
当有20个苹果的时候,最少需要:3个袋子
当有21个苹果的时候,最少需要:-1个袋子
当有22个苹果的时候,最少需要:3个袋子
当有23个苹果的时候,最少需要:-1个袋子
当有24个苹果的时候,最少需要:3个袋子
当有25个苹果的时候,最少需要:-1个袋子
当有26个苹果的时候,最少需要:4个袋子
当有27个苹果的时候,最少需要:-1个袋子
当有28个苹果的时候,最少需要:4个袋子
当有29个苹果的时候,最少需要:-1个袋子
当有30个苹果的时候,最少需要:4个袋子
当有31个苹果的时候,最少需要:-1个袋子
当有32个苹果的时候,最少需要:4个袋子
当有33个苹果的时候,最少需要:-1个袋子
当有34个苹果的时候,最少需要:5个袋子
当有35个苹果的时候,最少需要:-1个袋子
当有36个苹果的时候,最少需要:5个袋子
当有37个苹果的时候,最少需要:-1个袋子
当有38个苹果的时候,最少需要:5个袋子
当有39个苹果的时候,最少需要:-1个袋子
...

通过观察,可以得到如下结论

奇数个苹果,返回 -1。

n <= 5或者n==10的时候,返回 -1。

n == 6或者n == 8的时候,返回 1。

n % 8 == 0时候,全部用 8 号袋子,即n / 8; 当n%8!=0时,需要n/8+1个袋子。

代码可以优化为

    // 打表方式优化
    public static int minBags2(int n) {
        if (n <= 5 || n == 10 || (n & 1) == 1) {
            return -1;
        }
        if (n == 6 || n == 8) {
            return 1;
        }

        return n % 8 == 0 ? n / 8 : n / 8 + 1;
    }

牛羊吃草问题

牛客:青草游戏

暴力解法思路

n <= 4的情况下,我们可以通过观察得到牛羊的胜败情况

        // 0 羊胜
        // 1 牛胜
        // 2 羊胜
        // 3 牛胜
        // 4 牛胜
        if (n < 5) { // base case
            return (n == 0 || n == 2) ? "yang" : "niu";
        }

n >= 5的情况下,我们可以暴力枚举所有情况,

当牛选择吃 1 份的时候,接下来的子过程,是谁赢,如果子过程是牛赢,说明主过程是羊获胜了。
当牛选择吃 4 份的时候,接下来的子过程,是谁赢,如果子过程是牛赢,说明主过程是羊获胜了。
......
当牛选择吃 4^x 份的时候,接下来的子过程,是谁赢,如果子过程是牛赢,说明主过程是羊获胜了。 (注:4^x <= n)。

暴力解法的代码如下:

    public static String winner(int n) {
        // 0 羊
        // 1 牛
        // 2 羊
        // 3 牛
        // 4 牛
        if (n < 5) { // base case
            return (n == 0 || n == 2) ? "yang" : "niu";
        }
        // n >= 5 时
        int base = 1; // 当前先手(牛)决定吃的草数
        // 当前是先手(牛)在选
        while (base <= n) {
            // 当前一共n份草,先手(牛)吃掉的是base份,n - base 是留给后手(羊)的草
            if (winner(n - base).equals("yang")) {
                return "niu";
            }
            if (base > (n >> 2)) { // 防止base*4之后溢出
                break;
            }
            base <<= 2;
        }
        return "yang";
    }

打印出前面的一些输出

0 堆草,获胜者是:yang
1 堆草,获胜者是:niu
2 堆草,获胜者是:yang
3 堆草,获胜者是:niu
4 堆草,获胜者是:niu
5 堆草,获胜者是:yang
6 堆草,获胜者是:niu
7 堆草,获胜者是:yang
8 堆草,获胜者是:niu
9 堆草,获胜者是:niu
10 堆草,获胜者是:yang
11 堆草,获胜者是:niu
12 堆草,获胜者是:yang
13 堆草,获胜者是:niu
14 堆草,获胜者是:niu
15 堆草,获胜者是:yang
16 堆草,获胜者是:niu
17 堆草,获胜者是:yang
18 堆草,获胜者是:niu
19 堆草,获胜者是:niu
20 堆草,获胜者是:yang
21 堆草,获胜者是:niu
22 堆草,获胜者是:yang
23 堆草,获胜者是:niu
24 堆草,获胜者是:niu

通过观察可知,可以得到结论

n % 5 == 0 || n % 5 == 2情况下,获胜者都是羊,否则获胜者是牛。

优化后的代码如下:

    public static String winner2(int n) {
        if (n % 5 == 0 || n % 5 == 2) {
            return "yang";
        } else {
            return "niu";
        }
    }

判断一个数是否可以表示成若干(数量>1)连续正数和的数

题目描述如下

定义一种数:可以表示成若干(数量 > 1)连续正数和的数
比如:
5 = 2 + 3,5 就是这样的数
12 = 3 + 4 + 5,12 就是这样的数
1不是这样的数,因为要求数量大于1个、连续正数和
2 = 1 + 1,2 也不是,因为等号右边不是连续正数
给定一个参数 N,返回是不是可以表示成若干连续正数和的数

按照题目的描述,我们可以把暴力解法写出来,就是枚举 num 是否 可以被
1 + 2 + ... + n
2 + 3 + ... + n
3 + 4 + ... + n
...
上述任何一个式子分解。

暴力解法的代码如下

    public static boolean isMSum1(int num) {
        if (num <= 2) {
            return false;
        }
        int sum = 1;
        for (; sum < num; sum++) {
            int o = sum;
            int i = sum + 1;
            sum += i;
            if (sum > num) {
                return false;
            }
            while (sum < num) {
                i++;
                sum += i;
            }
            if (sum == num) {
                return true;
            }
            sum = o;
        }
        return false;
    }

打印出前面若干项的结果

1 : false
2 : false
3 : true
4 : false
5 : true
6 : true
7 : true
8 : false
9 : true
10 : true
11 : true
12 : true
13 : true
14 : true
15 : true
16 : false
17 : true
18 : true
19 : true
20 : true
21 : true
22 : true
23 : true
24 : true
25 : true
26 : true
27 : true
28 : true
29 : true
30 : true
31 : true
32 : false

观察后发现

num == 1 || num == 2时,为 false。

如果一个数是 2 的某次方,则返回 false,否则则返回 true。

如何判断一个数是不是 2 的某次方呢?

有如下三种方法

num == (num & (-num))
num == (num & (~num + 1))
(n & (num - 1)) == 0

所以,优化后的代码如下

    public static boolean isMSum2(int num) {
        if (num == 1 || num == 2) {
            return false;
        }
        return ((num - 1) & num) != 0;
    }

更多

算法和数据结构笔记

参考资料

算法和数据结构体系班-左程云

标签:打表法,最少,当有,袋子,苹果,使用,堆草,true,规律
From: https://www.cnblogs.com/greyzeng/p/16651527.html

相关文章

  • node31-gulp使用
     第一步安装 第二步建立文件夹 第三部src放源代码 第四步输入代码 执行 ......
  • 使用WooCommerce导入商品时,出现:File Type Is Not Permitted,怎么办?
    使用WordPress做电商独立站的时候,我们经常使用的插件是WooCommerce,我们公司也是如此。最近发现一个问题,从站点A往站点B导入产品的时候,提示:Sorry,ThisFileTypeIsNotPe......
  • nnUNet使用指南(四):json文件的配置
    代码如下fromcollectionsimportOrderedDictimportglobimportosimportreimportjsonfrombatchgenerators.utilities.file_and_folder_operationsimport*d......
  • 开源IPTV源服务程序使用教程
    Streaming-Media-Server-Pro前言我的目标是将程序打造成属于每个人的直播源服务,且对每个人完全开源免费!可作为家庭影院电视、视频等流媒体的提供商,兼容全平台,只需下载视......
  • Spring注解使用
    声明Bean的注解@Controller控制层@Service业务层@Repository持久化层以上三个注解都是@Component的延申,同时也是可以使用这个注解来替代以上三个注解的任意一......
  • BI_SQL盲注框架使用说明
    简介​ 这里是SQL盲注框架的使用说明文档,这个项目的初衷是为了解决在CTF中编写SQL盲注脚本的不便:大部分时间编写的SQL盲注脚本都是payload指向的,这就导致了基本上一个题要......
  • jszip基本使用及应用实例
    前言网页端操作将一堆文件批量操作打包成一个压缩包一次性下载给用户,现成的插件可以用jszip,需要了解底层可以自行阅读源码这里记录jszip的基本用法及自已项目需求下......
  • springboot的简单使用(3)
    1.5第五章接口架构风格—RESTful1.5.1认识RESTREST(英文:RepresentationalStateTransfer,简称REST)一种互联网软件架构设计的风格,但它并不是标准,它只是提出了一组客......
  • 过滤器和拦截器的使用
    过滤器和拦截器的使用拦截器应用场景拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:登录验证,判断用户是否登录。权......
  • HiveSql调优系列之Hive严格模式,如何合理使用Hive严格模式
    目录综述1.严格模式1.1参数设置1.2查看参数1.3严格模式限制内容及对应参数设置2.实际操作2.1分区表查询时必须指定分区2.2orderby必须指定limit2.3限制笛卡尔积3.搭......