【每日一题】823. 带因子的二叉树

【每日一题】823. 带因子的二叉树

  • 823. 带因子的二叉树
    • 题目描述
    • 解题思路

823. 带因子的二叉树

题目描述

给出一个含有不重复整数元素的数组 arr ,每个整数 arr[i] 均大于 1。

用这些整数来构建二叉树,每个整数可以使用任意次数。其中:每个非叶结点的值应等于它的两个子结点的值的乘积。

满足条件的二叉树一共有多少个?答案可能很大,返回 对 109 + 7 取余 的结果。

示例 1:

输入: arr = [2, 4]
输出: 3
解释: 可以得到这些二叉树: [2], [4], [4, 2, 2]

示例 2:

输入: arr = [2, 4, 5, 10]
输出: 7
解释: 可以得到这些二叉树: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2].

提示:

1 <= arr.length <= 1000
2 <= arr[i] <= 109
arr 中的所有值 互不相同

解题思路

思路:求解满足条件的二叉树有多少个,该如何求解保证唯一性呢?枚举根节点!由于整数的因子必定比该整数小,故可以先对整数数组进行排序。由于求解时只会使用到以整数数组元素作为根节点的二叉树数目,故dfs(i)的i表示数组下标,记忆化数组memo[i]的i也表示数组下标。其中i=j*k,i是当前乘积,j是乘积因子且j<i,如何查找k呢?使用arr[i]/arr[j]对应的下标,故此时需要使用umap将数组元素与下标对应。总而言之,即先对数组排序,接着将数组元素与对应下标进行映射,然后枚举数组元素,求解以每一个元素作为根节点的二叉树数量并进行累加,对于以某一节点i为根节点的二叉树数量求解方法为,枚举<i的节点j,判断是否能够在数组中找到k使得i=j*k,此处可以加入记忆化。

// 超时递归
class Solution {
public:const int MOD=1e9+7;int numFactoredBinaryTrees(vector<int>& arr) {// 存储数组元素 用于O(1)存取unordered_set<int> s(arr.begin(),arr.end());function<long long (int)> dfs=[&](int val) -> long long{// 如果val无分解因子 则相当于return 1long long res=1;// 遍历查找因子for(int x:arr){if(val%x==0&&s.count(val/x))res+=dfs(x)*dfs(val/x);}return res;};long long res=0;// 枚举每一个根节点for(int x:arr)res+=dfs(x);return res%MOD;}
};
// 通过 记忆化
class Solution {
public:const int MOD=1e9+7;int numFactoredBinaryTrees(vector<int>& arr) {// 对数组排序 方便记忆化sort(arr.begin(),arr.end());int n=arr.size();// 记忆化数组 vector<long long> memo(n,-1);// 存储数组元素 用于O(1)存取unordered_map<int,int> s;// 将数组元素与数组下标映射for(int i=0;i<n;i++)s[arr[i]]=i;function<long long (int)> dfs=[&](int i) -> long long{// 已经计算过则直接返回if(memo[i]!=-1)return memo[i];// 如果val无分解因子 则相当于return 1long long res=1;int val=arr[i];// 遍历查找因子for(int j=0;j<i;j++){int x=arr[j];if(val%x==0&&s.count(val/x))res+=dfs(j)*dfs(s[val/x]);}return memo[i]=res;};long long res=0;// 枚举每一个根节点 根节点只有一个 每个根节点不同即为不同 根节点代表唯一性for(int i=0;i<n;i++)res+=dfs(i);return res%MOD;}
};
// 通过 动态规划
class Solution {
public:const int MOD=1e9+7;int numFactoredBinaryTrees(vector<int>& arr) {// 对数组排序 方便记忆化sort(arr.begin(),arr.end());int n=arr.size();// 记忆化数组 vector<long long> f(n,1);// 存储数组元素 用于O(1)存取unordered_map<int,int> s;// 将数组元素与数组下标映射for(int i=0;i<n;i++)s[arr[i]]=i;for(int i=0;i<n;i++){int val=arr[i];// 遍历查找因子for(int j=0;j<i;j++){int x=arr[j];if(val%x==0&&s.count(val/x))f[i]+=f[j]*f[s[val/x]];}}long long res=0;// 枚举每一个根节点 根节点只有一个 每个根节点不同即为不同 根节点代表唯一性for(int i=0;i<n;i++)res+=f[i];return res%MOD;}
};
// 通过 动态规划+对称性
class Solution {
public:const int MOD=1e9+7;int numFactoredBinaryTrees(vector<int>& arr) {// 对数组排序 方便记忆化sort(arr.begin(),arr.end());int n=arr.size();// 记忆化数组 vector<long long> f(n,1);// 存储数组元素 用于O(1)存取unordered_map<int,int> s;// 将数组元素与数组下标映射for(int i=0;i<n;i++)s[arr[i]]=i;for(int i=0;i<n;i++){int val=arr[i];// 遍历查找因子for(int j=0;j<i;j++){int x=arr[j];// 算到一半即可if(1LL*x*x>val)break;// 临界点if(x*x==val){f[i]+=f[j]*f[j];break;}// 12 = 2*6 = 6*2if(val%x==0&&s.count(val/x))f[i]+=f[j]*f[s[val/x]]*2;}}long long res=0;// 枚举每一个根节点 根节点只有一个 每个根节点不同即为不同 根节点代表唯一性for(int i=0;i<n;i++)res+=f[i];return res%MOD;}
};

总结:递归->记忆化搜索->动态规划->滚动数组。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类和对象(下)

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

大模型综述论文笔记1-5

目录 KeywordsIntroductionSLMNLMPLMLLM Backgroud for LLMsScaling Laws for LLMsKM scaling lawChinchilla scaling law Emergent Abilities of LLMsIn-context learningInstruction followingStep-by-step reasoning Key Techniques for LLMsScalingTrainingAbility eliciti…

【uniapp】 实现公共弹窗的封装以及调用

图例&#xff1a;红框区域为 “ 内容区域 ” 一、组件 <!-- 弹窗组件 --> <template> <view class"add_popup" v-if"person.isShowPopup"><view class"popup_cont" :style"{width:props.width&&props.width&…

mybatis源码学习-1-调试环境

写在前面,这里会有很多借鉴的内容,有以下三个原因 本博客只是作为本人学习记录并用以分享,并不是专业的技术型博客笔者是位刚刚开始尝试阅读源码的人,对源码的阅读流程乃至整体架构并不熟悉,观看他人博客可以帮助我快速入门如果只是笔者自己观看,难免会有很多弄不懂乃至理解错误…

Spring源码解析-总览

1、前言 Spring源码一直贯穿我们Java的开发中&#xff0c;只要你是一个Java开发人员就一定知道Spring全家桶。Spring全家桶为我们一共一站式服务&#xff0c;IOC、AOP更是Spring显著特性。但是Spring到底怎么为我们提供容器&#xff0c;管理资源的呢&#xff1f;下来&#xff0…

MyBatis 中如何实现分页 ?

1. MyBatis 中如何实现分页 &#xff1f; MyBatis 中的分页有两种实现方式&#xff1a;物理分页 or 逻辑分页 【物理分页】 1.1 原生 SQL 物理分页 物理分页是通过 SQL 查询语句&#xff0c;LIMIT 语法进行分页的&#xff0c;它是在数据库引擎层面实现的。 <select id&…

Ubuntu学习---跟着绍发学linux课程记录(第二部分)

文章目录 7 文件权限7.1 文件的权限7.2 修改文件权限7.3 修改文件的属主 8、可执行脚本8.2Shell脚本8.3python脚本的创建 9Shell9.1Shell中的变量9.2 环境变量9.3用户环境变量 学习链接: Ubuntu 21.04乌班图 Linux使用教程_60集Linux课程 所有资料在 http://afanihao.cn/java …

学生管理系统VueAjax版本

学生管理系统VueAjax版本 使用Vue和Ajax对原有学生管理系统进行优化 1.准备工作 创建AjaxResult类&#xff0c;对Ajax回传的信息封装在对象中 package com.grg.Result;/*** Author Grg* Date 2023/8/30 8:51* PackageName:com.grg.Result* ClassName: AjaxResult* Descript…

Docker进入容器出现bash: vi: command not found

&#x1f388;1 参考文档 docker基础容器中bash: vi: command not found问题解决 | 你邻座的怪同学 &#x1f50d;2 问题描述 在使用 Docker 容器时&#xff0c;有时候里边没有安装vim&#xff0c;敲vim命令时提示说&#xff1a;vim: command not found。 这个时候就需要安装v…

Java抛出异常

当某个方法抛出了异常时&#xff0c;如果当前方法没有捕获异常&#xff0c;异常就会被抛到上层调用方法&#xff0c;直到遇到某个try ... catch被捕获为止 调用printStackTrace()可以打印异常的传播栈&#xff0c;对于调试非常有用&#xff1b;捕获异常并再次抛出新的异常时&am…

项目-IM

tim-server tim-server启动类实现CommandLineRunner接口&#xff0c;重写run()方法 run()方法开启一个线程&#xff0c;创建zk持久父节点&#xff0c;创建临时顺序子节点&#xff0c;将netty-server信息写入 1.1 用户登录 1.2 gateway向认证授权中心请求token 1.3 从zookee…

在windows上安装Cmake软件

Cmake是一个跨语言、跨平台、开源的编译工具&#xff0c;可以编译C、C、Note.js、JavaScript、C#、Java、Python、Php、Object-C、Ruby等工程&#xff0c;需要设置对应的src源码目录、ext第三方依赖目录、CMakeList.txt构建列表&#xff0c;再使用cmake命令即可。     2023年…

程序员自由创业周记#2:前期准备

感恩 上次公开了创业的决定后&#xff0c;得到了很多亲朋好友和陌生朋友的鼓励或支持&#xff0c;以不同的形式&#xff0c;感动之情溢于言表。这些都会记在心里&#xff0c;大恩不言谢~ 创业方向 笔者是一名资质平平的iOS开发程序猿&#xff0c;创业项目也就是开发App卖&am…

Jmeter(二十九):Jmeter常用场景梳理

一、每秒钟固定调用次数 如果想控制每秒发送请求数量,仅仅通过线程数与循环次数是不够的,因为这只能控制发送总数,而要控制每秒发送数量,需要线程数与常数吞吐量控制器的搭配使用,这种场景在性能测试中使用不多。 例如每秒钟调用30次接口,那么把线程数设置为30,将常数…

Netty-ChannelPipeline

EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 ChannelHandler 完成的&#xff0c;ChannelPipeline 和 ChannelHandler应用开发的过程…

高教社杯数模竞赛特辑论文篇-2012年A题:葡萄酒的评价(附获奖论文)

目录 摘 要 一、问题重述 二、问题分析 2.1 问题一的分析 2.2 问题二的分析

SMT制造中的产品质量检验和管理

SMT制造中的质量检验和产品物料管理都是实现高质量、低成本、高效益的重要方法。在SMT加工的过程中&#xff0c;产品质量的检验和质量把控都是重中之重&#xff0c;可以有效的降低产品不良率及返修等造成制造成本升高的风险问题&#xff0c;今天就来跟大家讨论一下SMT制造中我们…

C语言(第三十三天)

3.1.2 画图推演 3.2 举例2&#xff1a;顺序打印一个整数的每一位 输入一个整数m&#xff0c;打印这个按照顺序打印整数的每一位。 比如&#xff1a; 输入&#xff1a;1234 输出&#xff1a;1 2 3 4 输入&#xff1a;520 输出&#xff1a;5 2 0 3.2.1 分析和代码实现 这个题目&a…

数据结构--队列与循环队列

队列 队列是什么&#xff0c;先联想一下队&#xff0c;排队先来的人排前面先出&#xff0c;后来的人排后面后出&#xff1b;队列的性质也一样&#xff0c;先进队列的数据先出&#xff0c;后进队列的后出&#xff1b;就像图一的样子&#xff1a; 图1 如图1&#xff0c;1号元素是…

Harbor查看密码

已经登录过的harbor 查看密码 cat /root/.docker/config.json {"auths": {"172.28.120.140": {"auth": "YWRtaW43QDIwMTg"}}使用base64解码