Java玩转《啊哈算法》暴力枚举之坑爹奥数

每个笨蛋都会随时准备杀了自己,这是最怯懦,也是最简单的出路。

  • 缘起
  • 代码地址
  • 枚举
    • 题1
    • 题2
    • 题2 - Plus
    • 完整代码

缘起

各位小伙伴们好呀!本人最近看了下《啊哈算法》,写的确实不错。

但稍显遗憾的是,书籍示例代码是c语言,而不是本人常用的Java。

那就弥补遗憾,说干就干,把这本书的示例语言用java写一遍, 顺带附上一些自己的理解!

今天这篇博客讲的是如何用枚举来解一些奥数题
在这里插入图片描述

来不及买纸质书但又想尽快感受算法魅力的童鞋也甭担心,电子版的下载链接已经放到下方了,可尽情下载。

链接:https://pan.baidu.com/s/1imxiElcCorw2F-HJEnB-PA?pwd=jmgs
提取码:jmgs

代码地址

本文代码已开源:

git clone https://gitee.com/guqueyue/my-blog-demo.git

请切换到gitee分支,

然后查看aHaAlgorithm模块下的src/main/java/com/guqueyue/aHaAlgorithm/chapter_3_Enum即可!

枚举

按照惯例,首先我们来介绍一下枚举的概念:

枚举,又称穷举,说白了就是利用计算机的性能优势,暴力的穷尽每一种可能性,最后找到符合条件的情况。

在这里插入图片描述

这种思想很普遍、常用,反正遍历就对了!

下面,我们用三个奥数题,来揭开枚举的奥秘。

题1

小哼在数学课上遇到一道奥数题是这样的,口3x6528=30x8256,在两个口内填入相同的数字使得等式成立。

这一题很简单,直接遍历1-9这9个数字,看等式是否成立即可,轻松拿下:

   /**
     * @Description :[]3 x 6528 = 3[] x 8256, 再两个[]内填入相同的数字使得等式成立
     * @Param []
     * @return void
     **/
    private static void test1() {

        for (int i = 1; i <= 9; i++) {
            if ((i * 10 + 3) * 6528 == (30 + i) * 8256) {
                System.out.println(i + "3 x 6528 = 3"+ i +" x 8256");
            }
        }
    }

运行得(完整代码已开源,或者在后面查看):
在这里插入图片描述

题2

现在小哼又遇到一个稍微复杂一点的奥数题, 000+000-000,将数字1~9分别填入9个口中,每个数字只能使用一次使得等式成 立。例如173+286= 459就是一个合理的组合,请问一共有多少种合理的组合呢?注意: 173+286= 459 与286+173= 459是同一种组合 !

在这里插入图片描述
那么,这个题怎么做呢?

我们直接声明9个变量分别表示每个数,然后再采用9个for循环来暴力穷举每种情况,看看是否符合条件,并统计:

	/**
     * @Description :[][][] + [][][] = [][][], 分别填入 1-9,有多少种填法?
     *                a b c    d e f    g h i
     * @Param []
     * @return void
     **/
    private static void test2() {

        int a, b, c, d, e, f, g, h, i, total = 0;
        for (a = 1; a <= 9; a++) {
            for (b = 1; b <= 9; b++) {
                for (c = 1; c <= 9; c++) {
                    for (d = 1; d <= 9; d++) {
                        for (e = 1; e <= 9; e++) {
                            for (f = 1; f <= 9; f++) {
                                for (g = 1; g <= 9; g++) {
                                    for (h = 1; h <= 9; h++) {
                                        for (i = 1; i <= 9; i++) {
                                            if (a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i
                                                       && b != c && b != d && b != e && b != f && b != g && b != h && b != i
                                                                 && c != d && c != e && c != f && c != g && c != h && c != i
                                                                           && d != e && d != f && d != g && d != h && d != i
                                                                                     && e != f && e != g && e != h && e != i
                                                                                               && f != g && f != h && f != i
                                                                                                         && g != h && g != i
                                                                                                                   && h != i
                                                && a * 100 + b * 10 + c + d * 100 + e * 10 + f == g * 100 + h * 10 + i
                                            ) {
                                                System.out.println("" + a + b + c + " + " + d + e + f + " = " + g + h + i);
                                                total++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        System.out.println("情况为(种):" + total/2);
    }

运行得(完整代码已开源,或者在后面查看):

在这里插入图片描述

题2 - Plus

看了上文的代码,估计大家会觉得很恐怖,毕竟我打都打了半天。
如果要用一句歇后语来形容,那就是:封建社会老太太的裹脚布 —— 又臭又长。

在这里插入图片描述

上文的代码主要有两个问题:

  1. 声明变量太多容易让人搞错。
  2. 确定每个数互不相等的逻辑太过于冗长,简直让人崩溃。

在这里插入图片描述
那么,要怎么优化呢?我这里就不卖关子了,直接给出解决方案:

  1. 变量的话可以直接声明一个数组,不同的索引位置来存放不同数,清晰明了方便。
  2. 确定每个数互不相等的部分,可以采用一个标记数组:如果有这个数,标记为1;无,则标记为0。最后,将标记数组相加,若和为9,则每个数都互不相同。

优化代码如下:

	/**
     * @Description :[][][] + [][][] = [][][], 分别填入 1-9,有多少种填法?
     *                a b c    d e f    g h i
     * @Param []
     * @return void
     **/
    private static void test2Plus() {

        int[] a = new int[9]; // 用于存储
        int[] book = new int[10]; // 用于标记数字
        int total = 0;
        for (a[0] = 1; a[0] <= 9; a[0]++) {
            for (a[1] = 1; a[1] <= 9; a[1]++) {
                for (a[2] = 1; a[2] <= 9; a[2]++) {
                    for (a[3] = 1; a[3] <= 9; a[3]++) {
                        for (a[4] = 1; a[4] <= 9; a[4]++) {
                            for (a[5] = 1; a[5] <= 9; a[5]++) {
                                for (a[6] = 1; a[6] <= 9; a[6]++) {
                                    for (a[7] = 1; a[7] <= 9; a[7]++) {
                                        for (a[8] = 1; a[8] <= 9; a[8]++) {

                                            // 初始化 book 数组
                                            for (int i = 1; i < 10; i++) {
                                                book[i] = 0;
                                            }

                                            // 标记
                                            for (int i = 0; i < 9; i++) {
                                                book[a[i]] = 1;
                                            }

                                            int sum = 0;
                                            for (int i = 1; i <= 9; i++) {
                                                sum += book[i];
                                            }

                                            if (sum == 9
                                                    && a[0] * 100 + a[1] * 10 + a[2] + a[3] * 100 + a[4] * 10 + a[5] == a[6] * 100 + a[7] * 10 + a[8]) {
                                                System.out.println("" + a[0] + a[1] + a[2] + " + " + a[3] + a[4] + a[5] + " = " + a[6] + a[7] + a[8]);
                                                total++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        System.out.println("情况为(种):" + total/2);
    }

是不是好很多呢?运行,可得(完整代码已开源,或者在后面查看):

在这里插入图片描述

完整代码

package com.guqueyue.aHaAlgorithm.chapter_3_Enum;

/**
 * @Author: guqueyue
 * @Description: 枚举求奥数题
 * @Date: 2024/1/16
 **/
public class Test {
    public static void main(String[] args) {

//        test1();
//        test2();
        test2Plus();
    }

    /**
     * @Description :[]3 x 6528 = 3[] x 8256, 再两个[]内填入相同的数字使得等式成立
     * @Param []
     * @return void
     **/
    private static void test1() {

        for (int i = 1; i <= 9; i++) {
            if ((i * 10 + 3) * 6528 == (30 + i) * 8256) {
                System.out.println(i + "3 x 6528 = 3"+ i +" x 8256");
            }
        }
    }

    /**
     * @Description :[][][] + [][][] = [][][], 分别填入 1-9,有多少种填法?
     *                a b c    d e f    g h i
     * @Param []
     * @return void
     **/
    private static void test2() {

        int a, b, c, d, e, f, g, h, i, total = 0;
        for (a = 1; a <= 9; a++) {
            for (b = 1; b <= 9; b++) {
                for (c = 1; c <= 9; c++) {
                    for (d = 1; d <= 9; d++) {
                        for (e = 1; e <= 9; e++) {
                            for (f = 1; f <= 9; f++) {
                                for (g = 1; g <= 9; g++) {
                                    for (h = 1; h <= 9; h++) {
                                        for (i = 1; i <= 9; i++) {
                                            if (a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i
                                                       && b != c && b != d && b != e && b != f && b != g && b != h && b != i
                                                                 && c != d && c != e && c != f && c != g && c != h && c != i
                                                                           && d != e && d != f && d != g && d != h && d != i
                                                                                     && e != f && e != g && e != h && e != i
                                                                                               && f != g && f != h && f != i
                                                                                                         && g != h && g != i
                                                                                                                   && h != i
                                                && a * 100 + b * 10 + c + d * 100 + e * 10 + f == g * 100 + h * 10 + i
                                            ) {
                                                System.out.println("" + a + b + c + " + " + d + e + f + " = " + g + h + i);
                                                total++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        System.out.println("情况为(种):" + total/2);
    }

    /**
     * @Description :[][][] + [][][] = [][][], 分别填入 1-9,有多少种填法?
     *                a b c    d e f    g h i
     * @Param []
     * @return void
     **/
    private static void test2Plus() {

        int[] a = new int[9]; // 用于存储
        int[] book = new int[10]; // 用于标记数字
        int total = 0;
        for (a[0] = 1; a[0] <= 9; a[0]++) {
            for (a[1] = 1; a[1] <= 9; a[1]++) {
                for (a[2] = 1; a[2] <= 9; a[2]++) {
                    for (a[3] = 1; a[3] <= 9; a[3]++) {
                        for (a[4] = 1; a[4] <= 9; a[4]++) {
                            for (a[5] = 1; a[5] <= 9; a[5]++) {
                                for (a[6] = 1; a[6] <= 9; a[6]++) {
                                    for (a[7] = 1; a[7] <= 9; a[7]++) {
                                        for (a[8] = 1; a[8] <= 9; a[8]++) {

                                            // 初始化 book 数组
                                            for (int i = 1; i < 10; i++) {
                                                book[i] = 0;
                                            }

                                            // 标记
                                            for (int i = 0; i < 9; i++) {
                                                book[a[i]] = 1;
                                            }

                                            int sum = 0;
                                            for (int i = 1; i <= 9; i++) {
                                                sum += book[i];
                                            }

                                            if (sum == 9
                                                    && a[0] * 100 + a[1] * 10 + a[2] + a[3] * 100 + a[4] * 10 + a[5] == a[6] * 100 + a[7] * 10 + a[8]) {
                                                System.out.println("" + a[0] + a[1] + a[2] + " + " + a[3] + a[4] + a[5] + " = " + a[6] + a[7] + a[8]);
                                                total++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        System.out.println("情况为(种):" + total/2);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法修炼-动态规划之斐波那契数列模型

一、动态规划的算法原理 这是本人动态规划的第一篇文章&#xff0c;所以先阐述一下动态规划的算法原理以及做题步骤。动态规划本人的理解就是通过题目所给的条件正确地填满dp表&#xff08;一段数组&#xff09;。首先要先确定好dp表每个位置的值所代表的含义是什么&#xff0c…

二叉树的增删查改

本节复习二叉树的增删查改&#xff0c; 二叉树的知识相对于前面的循序表&#xff0c; 链表&#xff0c; 以及栈和队列都要多一些。 同时二叉树的增删查改理解起来相对来说要困难一些。 本节来好好复习一下二叉树的增删查改。 目录 准备文件 创建结构体蓝图 二叉树的前序遍历…

Windows PowerShell 命令行历史记录补全

Windows 命令行历史记录补全 使用 powershell 安装PSReadLine 2.1.0 Install-Module PSReadLine -RequiredVersion 2.1.0检查是否存在配置文件 Test-path $profile # 为 false 则执行命令创建 New-item –type file –force $profile编辑配置文件 notepad $profile# 输入如下…

数据结构------栈(Stack)和队列(Queue)

也是好久没写博客了&#xff0c;那今天就回归一下&#xff0c;写一篇数据结构的博客吧。今天要写的是栈和队列&#xff0c;也是数据结构中比较基础的知识。那么下面开始今天要写的博客了。 目录 栈&#xff08;Stack&#xff09; 队列&#xff08;Queue&#xff09; 喜欢就点…

从C到C++

二、从C到C 本章介绍一些C拓展的非面向对象功能。 引用&#xff08;掌握&#xff09; 1.1 概念 引用从一定程度上讲是一个指针的平替&#xff0c;几乎被所有面向对象编程语言所使用。引用相当于对某一个目标变量起”别名“。 操作引用与操作原变量完全一样。 #include <iost…

工厂模式 详解 设计模式

工厂模式 其主要目的是封装对象的创建过程&#xff0c;使客户端代码和具体的对象实现解耦。这样子就不用每次都new对象&#xff0c;更换对象的话&#xff0c;所有new对象的地方也要修改&#xff0c;违背了开闭原则&#xff08;对扩展开放&#xff0c;对修改关闭&#xff09;。…

Unity UI适配规则和对热门游戏适配策略的拆解

前言 本文会介绍一些关于UI适配的基础概念&#xff0c;并且统计了市面上常见的设备的分辨率的情况。同时通过拆解目前市面上较为成功的两款休闲游戏Royal Match和Monopoly GO(两款均为近期游戏付费榜前几的游戏)&#xff0c;大致推断出他们的适配策略&#xff0c;以供学习和参…

go并发模式之----阻塞/屏障模式

常见模式之一&#xff1a;阻塞/屏障模式 定义 顾名思义&#xff0c;就是阻塞等待所有goroutine&#xff0c;直到所有goroutine完成&#xff0c;聚合所有结果 使用场景 多个网络请求&#xff0c;聚合结果 大任务拆分成多个子任务&#xff0c;聚合结果 示例 package main ​…

Delegate动画案例(P30 5.6delegate动画)

一、ListElement&#xff0c;ListModel&#xff0c;ListView 1. ListElement ListElement 是 QML 中用于定义列表项的元素。它可以包含多个属性&#xff0c;每个属性对应列表项中的一个数据字段。通过在 ListModel 中使用 ListElement&#xff0c;可以定义一个列表的数据模型…

USB-C接口:办公新宠,一线连接笔记本与显示器

USB-C接口如今已成为笔记本与显示器连接的优选方案。无需担心正反插错&#xff0c;支持雷电4和DP视频信号输出&#xff0c;高速数据传输&#xff0c;还有最高100W的快充功能&#xff0c;真是方便又实用&#xff01; 一线连接&#xff0c;多功能融合 通过这个接口&#xff0c;你…

面试笔记系列三之spring基础知识点整理及常见面试题

目录 如何实现一个IOC容器? 说说你对Spring 的理解&#xff1f; 你觉得Spring的核心是什么&#xff1f; 说一下使用spring的优势&#xff1f; Spring是如何简化开发的&#xff1f; IOC 运行时序 prepareRefresh() 初始化上下文环境 obtainFreshBeanFactory() 创建并…

瑞_23种设计模式_外观模式

文章目录 1 外观模式&#xff08;Facade Pattern&#xff09;1.1 介绍1.2 概述1.3 外观模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 jdk源码解析 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《23种设计模式》的外观模式篇。本文中的部分…

如何在Windows部署TortoiseSVN客户端并实现公网连接内网VisualSVN服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

Flutter开发之Slider

Flutter开发之Slider 本文是关于介绍Slider相关属性的含义。 class SliderThemeData {/// slider轨道的高度 final double? trackHeight; /// 滑块滑过的轨道颜色 final Color? activeTrackColor; /// 滑块未滑过的轨道颜色 final Color? inactiveTrackColor; /// 滑块滑过…

JavaEE——简单认识JavaScript

文章目录 一、简单认识 JavaScript 的组成二、基本的输入输出和简单语法三、变量的使用四、JS 中的动态类型图示解释常见语言的类型形式 五、JS中的数组六、JS 中的函数七、JS 中的对象 一、简单认识 JavaScript 的组成 对于 JavaScript &#xff0c;其中的组成大致分为下面的…

多线程如何设计?一对多/多对一/多对多

二、14个多线程设计模式 参考原文&#xff1a;https://www.cnblogs.com/rainbowbridge/p/17443503.html single Thread 模式 一座桥只能通过一个人 Single Thread模式是一种单线程设计模式&#xff0c;即在一个应用程序中只有一个主线程、一个事件循环&#xff0c;对外只提…

【C语言基础】:深入理解指针(一)

文章目录 一、内存和地址1. 内存2. 如何理解编址 二、指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 如何拆解指针变量2.2.3 解引用操作符 2.3 指针变量的大小 三、指针变量类型的意义3.1 指针的解引用3.2 指针 - 整数3.3 void*指针…

什么是物联网?

今天这篇文章写的相关内容就是带领大家了解什么是物联网&#xff0c;之前写的文章大多都是一些物联网的未来&#xff0c;行业的解决方案等&#xff1b;话不多说开始进入正题吧! 物联网(IoT)是一个包罗万象的术语&#xff0c;指的是越来越多的电子产品&#xff0c;它们不是传统的…

vue2+elementui上传照片(el-upload 超简单)

文章目录 element上传附件&#xff08;el-upload 超详细&#xff09;代码展示html代码data中methods中接口写法 总结 element上传附件&#xff08;el-upload 超详细&#xff09; 这个功能其实比较常见的功能&#xff0c;后台管理系统基本上都有&#xff0c;这就离不开element的…

计算机组成原理4-存储器的层次结构与程序访问的局部性原理

1. 磁盘 1.磁盘的结构 磁盘由盘片构成&#xff0c;每个盘片包含两面 每面由一组称为磁道的同心圆组成 每个磁道划分为一组扇区&#xff0c;扇区之间由间隙隔开 同一半径上的所有磁道组成一个柱面2.磁盘的容量 容量&#xff1a;磁盘上可以存储的最大位数。 决定因素&#xff1a…