Java Stream来写算法01——自幂数(水仙花数)
总目录
思考
1.由于位数不同,导致算法不同,所以简化一下,只查找指定位数的自幂数,即指定nnn的值,如果让n=3n=3n=3,就是只查找100到999之间的自幂数。接下来的说法都以3位数来举例
2.需要将这个3位数中每一位的数取出来,取出后计算其3次幂的值
3.取每一位数的方法很多,这里使用与100相除的商来取百位,余数再与10相除,商为十位,余数再与1相除,商为个位数的方法
4.使用的方法中要尽量少用for、while语句
步骤1-初始化准备代码
计算3次幂的方法。
private int getPower(int initVal, int len) {return IntStream.iterate(initVal, v1 -> v1).limit(len).reduce(1, (a, b) -> a * b);
}
- 这个代码可以用Math.power函数来实现,这里是个小炫技,求轻打
- 参数len表示有多少位,initVal表示生成数列中包含的值。
getPower(5, 3)
为例,IntStream.iterate(initVal, v1->v1)
就会生成一个无限流,里面的内容全部都是5。limit(len)
,是让这个无限流,只会有3个5,其他的全抛弃。reduce(1, (a, b) -> a * b)
是把这个流收敛,可以理解成把分散的流变成一个值,这里使用的收敛方法,让流中每个元素相乘在一起,最后就是形成5∗5∗55*5*55∗5∗5这样的效果,即最后方法得到的是125,5的3次幂的值。- 灵活使用这个方法
getPower(10, 2)
,就可以得到100,是生成百位数时,要用到的第一个除数。 - 当得到了100,就可以得到3位数中最大值999,以及最小值100:
int firstDivide = getPower(10, len - 1);
int max = firstDivide * 10 -1;
int min = firstDivide;
步骤2-核心逻辑判断代码
非常遗憾地告诉各位,在这部分代码中,不得不使用的for循环,我也不想啊,可是现实就是让你低头啊,如果列位有更好解决方案,万望不吝赐教。
private IntPredicate isSelfPower(int len, int firstDivide) {return e -> {int dividend = e;// 被除数int divisor = firstDivide;// 除数int quotient;// 商int remainder;// 余数int sum = 0;for (int i = 0; i < len; i++) {quotient = dividend / divisor;remainder = dividend % divisor;sum += getPower(quotient, len);dividend = remainder;divisor /= 10;}return sum == e;};
}
IntPredicate
是一个函数式接口,返回真或假,而如何判断是应该返回真,还是返回假,全在return语句后面的实现代码中。- 实现代码中循环语句的作用举例来说就是:先解析出百位的数,然后对这个数求其3次幂的值,并加到sum变量中,然后再解析出十位的数,再求3次幂,并加到sum变量中……这样的循环。
- 解析百位数是除以100,解析十位是除以10,解析个位是除以1(这是比较无用的,但可以不用单独处理个位,保证代码的一致性)
- 最后就是比较这个和sum与这个数本身是不是一样,如果是true,则说明是自幂,反之则不是
步骤3-用一行代码实现查找自幂数
IntStream.iterate(min, v -> v + 1).limit(max - min).parallel().filter(isSelfPower(len, firstDivide)).forEach(System.out::println);
- 这里面生成的数列的lambda表达式是v -> v+1,这个会生成1,2,3,4,5……这样递增的数列。
- 使用parallel(),可以并行查找,如果把位数设的大一点,应该会有性能提升,但提升了多少,没有测试过,懒啊。
总结
把代码合并起来,就可以计算指定位数的自幂数了,如果设成8位数,可真是要算很长时间的。
之后的优化
- 核心逻辑判断代码是用一个方法返回函数式接口的实例,其实可以用属性来代替
- 在判断逻辑代码中使用了很多变量,也可以大幅度优化,修改后代码如下:
@FunctionalInterface
public interface ThreeParamPredicate<E> {boolean test(E e1, E e2, E e3);
}
private ThreeParamPredicate<Integer> threeParamPredicate = (len, divisor, dividend) -> {int sum = 0;for (int i = 0; i < len; i++) {int quotient = dividend / divisor;int remainder = dividend % divisor;sum += Double.valueOf(Math.pow(quotient, len)).intValue();dividend = remainder;divisor /= 10;}return sum == dividend;
}
- 举例说明一下这个代码的作用:
- 由于代码需要传入三个参数,而函数式接口中没有提供,所以自己写了一个接收三个入参的函数式接口
- 比如判断153是不是自幂数,首先要把153折成1、5、3三个数
- 循环第1次就是先拆出1这个数来,然后求1的3次幂,加到
sum
变量中 - 循环第2次拆出5来,求出5的3次幂,再加到
sum
变量中 - 循环第3次拆出3来,求出3的3次幂,再加到
sum
变量中 - 最后比较
sum
变量的值与153的比较,相等则说明是自幂数 - 但是这些代码,没有按照希望写出不带for/while语句的代码,所以再次修改如下
private IntPredicate isSelfPower1 = v -> {String str = String.valueOf(v);int len = str.length();int sum = Arrays.stream(str.split("")).mapToInt(e -> Double.valueOf(Math.pow(Integer.valueOf(e), len)).intValue()).sum();return v == sum;
}
- 这个代码意思是,先数字转换成字符串,求出其长度,再通过字符串,把每一个字符拆解出来,再转成数字,求幂值,最后求和
- 通过这个代码优化,可以看出之前写的代码,把数字长度做为参数传进来,还把除数也传入,是完全没必要的
- 这里面完全没有for/while语句了,很好啊!
Java Stream来写算法01——自幂数(水仙花数)相关推荐
- Java Stream来写算法10——毕达哥拉斯Pythagoras——勾股定理数
总目录 分析 除了等腰直角三角形,求解全部勾股数,需要知道求解两个正整数,m,nm, nm,n 这两个数要满足如下条件 序号 条件内容 1 m>nm > nm>n 2 mmm与nnn ...
- Java Stream如何写出高雅又装*的代码
Java Stream如何写出高雅又装*的代码 一. 冷静分析 二. 直接开装 2.1 初级炫 2.2 普通炫 2.3 高级炫 2.4 再炫一波 拿到当前key与对应的数量 2.5 Map Reduc ...
- Java 求解自幂数(水仙花数)
文章目录 什么是自幂数 Java pow() 方法扩展 如何求自幂数 什么是水仙花数 如何求水仙花数 附:常见水仙花数 什么是自幂数 如果在一个固定的进制中,一个 n 位自然数等于自身各个数位上数字的 ...
- 【C语言】(百合花)水仙花数的算法思考习题4-6 水仙花数
题目:水仙花数是指该N位数的各位的N次方之和等于其本身: 先写出较为简单的三位水仙花数 代码如下: #include<stdio.h> int main() {int i,t,n,sum; ...
- java使用for循环打印出所有的水仙花数
import java.util.Scanner; class Shuixianhua {public static void main(String[] args) {//使用for循环打印出所有的 ...
- 用php写水仙花及思路,php水仙花数
"水仙花数"指一个三位整数数中,个十百位的立方之和等于这个数的本身.比如整数:153就是水仙花数,因为:153 = 1³ + 5³ + 3³ .在计算时需要分别计算出个十百位的值, ...
- 用Java编写求出100~999之间的水仙花数
关键是求十位数:153 % 100 = 53,然后53 / 10 = 5 package day_2023_4_4;public class ShuiTest {public static void ...
- 什么是水仙花数,使用Java的for循环简单输出100~999的水仙花数和个数
水仙花是一种很美丽的花,那我们数学领域中有一种数字也是和水仙花般美的数字,叫做水仙花数,那么这种数字和其他数字有什么区别呢?水仙花数的特别之处在哪呢? 首先,水仙花数是一个三位数,也就是说,水仙花数的 ...
- java矩阵连乘算法_使用java写的矩阵乘法实例(Strassen算法)
Strassen算法于1969年由德国数学家Strassen提出,该方法引入七个中间变量,每个中间变量都只需要进行一次乘法运算.而朴素算法却需要进行8次乘法运算. 原理 Strassen算法的原理如下 ...
最新文章
- JQuery整体简化学习
- iphone电池怎么保养_怎么保持iPhone的电池健康?掌握这4个方面,3年不用换电池...
- dubbo学习之服务消费者
- Highly Available (Mirrored) Queues
- C# 中使用HttpClient读取大型Json数据集
- sklearn集合算法预测泰坦尼克号幸存者
- C++ 深拷贝和浅拷贝
- 线程八锁,同步锁的应用
- 数据挖掘:模型选择——集成算法与树模型
- Linux内核启动过程
- String 常用方法总结
- 你真的懂协程 (Coroutine) 吗 ? Kotlin Coroutines — Suspending Functions
- 国家开放大学专科计算机应用实训项目,国家开放大学电大专科《微机系统与维护》网络课实训1实训3作业及答案.docx...
- java毕业设计智能小区物业管理系统Mybatis+系统+数据库+调试部署
- 我们的宇宙,在某种意义上,是最好的一个
- 经典Excel VBA代码
- hdu 1735 文字统计
- H3C 不同版本登录认证配置
- 怎么入驻亚马逊跨境电商平台?
- Python——创建二维列表的简易方法
热门文章
- 淘宝商品详情API接口(网页版,APP端二合一接口)
- win7matlab2016启动闪退,大白菜修复win7系统启动matlab出现闪退的图文方案
- 封闭解、解析解和数值解定义
- Single Image Haze Removal Using Dark Channel Prior 基于暗原色先验的单一图像去雾方法【翻译】
- 虹科分享 | 基于流的流量分类的工作原理 | 网络流量监控
- 红帽 RHCSA笔记
- 网络层路由选择协议(RIPOSF)
- 全球与中国云合同管理软件市场深度研究分析报告
- 牢记这一波CAD快捷键,制图速度坐火箭!
- Android 模仿淘宝历史记录,记录存在手机内