阿亮的算法之路——279完全平方数

2024-01-07 02:59
文章标签 算法 完全 平方 279 阿亮

本文主要是介绍阿亮的算法之路——279完全平方数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

动态规划集中练习

题目详情

题目详情

自己尝试

因为是动态规划的集中练习,所以第一思路就是用动态规划去做。其实这种后面的会受到前面的影响的题,大都会第一想到动态规划。

这题我想了一会儿,有了大概的思路,
思路就是:
状态转移:当前n的最小次数= 所有可以组成n的两个整数的最小次数的和中最小的

第一次代码
    public static int numSquares(int n ){int [] dp = new int[n+1];for (int i = 1; i <= Math.sqrt(n); i++){ dp[i * i] = 1; }int [] array = new int[n/2];for (int i = 2; i <= n; i++){for (int j = 1; j <= i/2; j++){ array[j-1] = dp[j] +dp[i-j]; }if (dp[i] == 0){dp[i] = array[0];for (int anArray : array){if (anArray != 0 && dp[i] > anArray){ dp[i] = anArray; }}}}return dp[n] ;}

提交结果
提交结果
可以完成功能,但是有三层for循环,将速度拉得很慢很慢。偶尔一次可以提交通过,很多时候会超时,总是被最后 数很大的用例卡住。

第二次代码

尝试将代码优化,然后将一个数组换成了ArrayList

    public static int numSquares(int n ){int [] dp = new int[n+1];for (int i = 1; i <= Math.sqrt(n);i++ ){ dp[i*i]  = 1; }ArrayList<Integer> array = new ArrayList<>();for (int i = 2; i <= n; i++){for (int j = 1; j <= i/2; j++){ array.add(j-1,dp[j] +dp[i-j]) ; }if (dp[i] == 0){dp[i] = Collections.min(array);array.clear();}}return dp[n] ;}

自己测试也是可以完成功能的,但是提交直接超时。测试总用例588个,第一次还能坚持到最后一个用例,这次才520多个用例就超时了。

说明ArrayList的效率比数组要低,其实想想也是,ArrayList是对数组的封装,如果没有指定初始化容量,当需要的容量大了之后,会进行频繁的数组复制扩容。

第三次代码
        int [] dp = new int[n+1];for (int i = 1; i <= Math.sqrt(n);i++ ){ dp[i*i]  = 1; }int [] array = new int[n/2];for (int i = 2; i <= n; i++){if (dp[i] == 0){dp[i] = dp[1] + dp[i - 1];for (int j = 2; j <= i / 2; j++){ dp[i] = dp[i] > dp[j] + dp[i - j] ? dp[j] + dp[i - j] : dp[i]; }}}return dp[n] ;

进行了优化,少了一层for循环
提交结果这次可以稳定通过,但是还是很差,

第四次代码

思考如何能再次优化,在获取最小次数的时候,如果次数是2,那我就直接结束最内层循环,跳到最外层循环,因为次数为1的数,肯定是一些完全平方数,那么剩下的数,是2的肯是最小的了。

    public static int numSquares(int n ){int [] dp = new int[n+1];for (int i = 1; i <= Math.sqrt(n);i++ ){ dp[i*i]  = 1; }int [] array = new int[n/2];a:for (int i = 2; i <= n; i++){if (dp[i] == 0){dp[i] = dp[1] + dp[i - 1];for (int j = i/2; j >=  2; j--){dp[i] = dp[i] > dp[j] + dp[i - j] ? dp[j] + dp[i - j] : dp[i];if (dp[i] == 2){ continue a; }}}}return dp[n] ;

如此一来,效率果然大幅度提升,
提交结果比上一次直接提高了两倍,但是还是很差,所有提交通过中最末尾的。

大佬思路

无论我再怎么优化,总是需要几百毫秒,虽然比我一开始有很大的进步,但是水平来看,都是很差的,难道是我的思路不对??

寻思着大佬是怎么做的,就去看了一下大佬的代码

        int[] dp = new int[n + 1]; // 默认初始化值都为0for (int i = 1; i <= n; i++){dp[i] = i; // 最坏的情况就是每次+1for (int j = 1; i - j * j >= 0; j++){dp[i] = Math.min(dp[i], dp[i - j * j] + 1); // 动态转移方程}}return dp[n];

提交结果
提交结果果然很优秀,但其实他的思路和我一模一样,但是处理得很巧妙。

这篇关于阿亮的算法之路——279完全平方数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/578511

相关文章

Python使用Reflex构建现代Web应用的完全指南

《Python使用Reflex构建现代Web应用的完全指南》这篇文章为大家深入介绍了Reflex框架的设计理念,技术特性,项目结构,核心API,实际开发流程以及与其他框架的对比和部署建议,感兴趣的小伙... 目录什么是 ReFlex?为什么选择 Reflex?安装与环境配置构建你的第一个应用核心概念解析组件

Python日期和时间完全指南与实战

《Python日期和时间完全指南与实战》在软件开发领域,‌日期时间处理‌是贯穿系统设计全生命周期的重要基础能力,本文将深入解析Python日期时间的‌七大核心模块‌,通过‌企业级代码案例‌揭示最佳实践... 目录一、背景与核心价值二、核心模块详解与实战2.1 datetime模块四剑客2.2 时区处理黄金法

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Linux find 命令完全指南及核心用法

《Linuxfind命令完全指南及核心用法》find是Linux系统最强大的文件搜索工具,支持嵌套遍历、条件筛选、执行动作,下面给大家介绍Linuxfind命令完全指南,感兴趣的朋友一起看看吧... 目录一、基础搜索模式1. 按文件名搜索(精确/模糊匹配)2. 排除指定目录/文件二、根据文件类型筛选三、时间