823. 带因子的二叉树

做这题我的心中是十分难受的,sad,花了4个小时,没有通过。

主要是遇到https://leetcode-cn.com/submissions/detail/10936917/testcase/这个测试点过不了。

我觉得是取余那一块有点问题,但自认为逻辑是没有错的。也就是下面的代码是没有AC的代码。

 

题目描述:

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

我们用这些整数来构建二叉树,每个整数可以使用任意次数。

其中:每个非叶结点的值应等于它的两个子结点的值的乘积。

满足条件的二叉树一共有多少个?返回的结果应模除 10 ** 9 + 7。

示例 1:

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

示例 2:

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

提示:

  1. 1 <= A.length <= 1000.
  2. 2 <= A[i] <= 10 ^ 9.

题意:

看示例就可以明白并不是要真的建一颗树,而是找出符合要求的排列组合。单个因子也算是符合要求。

以示例2为例,有7个组合符合要求。其中,2作为父节点的出现1次,4作为父节点出现两次,5作为父节点出现1次,10作为父节点出现3次。

所有的输出就是各个元素作为父节点出现的次数之和。

问题转换为求每个元素作为父节点的次数。

算法:

先看示例2:

  看元素4,它除了有单个元素作为一种答案,还有[4,2,2]这样。所以总的次数变为了1+1=2;

  看元素10它,除了有单个元素作为一种答案,还有[10,2,5], [10,5,2]。总的次数变为了1+2=3.

  上面1次就差在4的两个子节点一样,而10的两个子节点不一样,可以调换位置。

示例2能得到的信息貌似就这么多了,自己再想个示例,[2,4,5,8]。这个示例的输出个数好像会比示例2多。

  [2,4,5,8]穷举一下,看看有哪几种。[2], [4], [5], [8]; [4,2,2], [8,4,2], [8,2,4]; [8,4,2,2,2]; [8,2,4,2,2],以上组合都以层次遍历的方式排列。

  统计下,一共有9次输出,以2为父节点1次,4为父节点2次,5为父节点1次,8为父节点5次。

  研究下元素8吧:

    它的子节点从2,4中取,那会不会和(以2为父节点的次数1次)、(以4为父节点2次)这个两个数字有关。

    好像是以8为父节点的次数5 = 1 * 2 * 2 + 1;实际上这就是我找的规律。

    等式右边一共有4个数字,

    第一个数字1:是以2为父节点的次数;

    第二个数字2:是以4为父节点的次数;

    第三个数字2: 它是一个参数,当父节点两边的因子一样时,它取1,如示例2中,父节点4出现的次数2 = 1 * 1 * 1 + 1;不一样时,它取2;

    第四个数字1:它是父节点8被赋的初始值。

  可以随便想个示例,看看上面这个规律是不是适用。

思路:

  1. 对输入数组A从小到大排序,方便顺序遍历
  2. 用一个map容器记录m元素作为父节点出现的次数。对A遍历一遍,每个元素加入到m中,并且赋初值为1。

  3. 主函数是两个for循环,进行m中值的更新,所有更新不是一步到位。比如一开始某个元素parent通过它的一个child更新了,后来child出现的次数增加了,
    parent的次数也要作相应增加。

通过文字想表达清楚意思实在太难了,画图工程量太大。直接上我的代码吧,只要不要像一开始的那种程度的测试点,应该都能过。

  1 #include <iostream>
  2 #include <vector>
  3 #include <cmath>
  4 #include <algorithm>
  5 #include <map>
  6 using namespace std;
  7 
  8 class Solution {
  9 public:
 10     long long INF;
 11     map<int, vector<int> > father;                          //map<a, vec> ;vec存储的是以a为乘子的A中元素
 12     map<int, unsigned long long> m;
 13 
 14     int numFactoredBinaryTrees(vector<int>& A) {
 15         //paremeters                                        
 16         int backSum = 0, len = A.size();                      
 17         INF = pow(10, 9) + 7;
 18         //init
 19         sort(A.begin(), A.end());
 20         for (int i = 0; i < len; i++)
 21             m[A[i]] = 1;
 22         
 23         //process
 24         for (int i = 0; i < len; i++)
 25         {
 26             for (int j = i; j < len; j++)
 27             {
 28                 unsigned long long mul = A[i] * A[j];
 29                 unsigned long long more;
 30 
 31                 if(m.find(mul) != m.end())                      //两者的乘积也在数组A中
 32                 {
 33                     father[A[i]].push_back(mul);                //A[i]是父亲mul的乘子
 34                     if(i == j)
 35                     {
 36                        more = m[A[i]] * m[A[j]];                //more是mul次数应该增加的部分
 37                     }
 38                     else
 39                     {
 40                         father[A[j]].push_back(mul);            //A[j]是父亲mul的乘子
 41                         more = m[A[i]] * m[A[j]] * 2;           //more是mul次数应该增加的部分
 42                     }
 43 
 44                     m[mul] += more;
 45                     updateFatherOf(mul, more);                  //mul已经更新了,顺便也要更新以它的乘子的父亲们
 46                 }
 47             }
 48         }
 49 
 50         int cnt = 0;
 51         //output
 52         for(auto i : m)
 53         {
 54             if(cnt < len)
 55             {
 56                 cnt++;
 57                 cout << i.first << ":" << i.second;
 58                 if(cnt % 10 == 0)
 59                     cout << endl;
 60                 else
 61                     cout << ' ';
 62             }
 63             int f;
 64             if(i.second >= INF)
 65                 f %= INF;
 66             else
 67                 f = i.second;
 68     
 69             backSum %= INF;
 70             backSum += f;
 71         }
 72         return backSum;
 73     }
 74 
 75     void updateFatherOf(int x, unsigned long long  exceed)                 
 76     {
 77         for(auto f : father[x])                                             
 78         {
 79             int another = f / x;
 80             if (another == x)
 81             {
 82                 m[f] += exceed * exceed;
 83                 updateFatherOf(f, exceed * exceed);            //f是x的父亲之一,f更新了,要以f为乘子对f所有的父亲进行更新
 84             }
 85             else 
 86             {
 87                 m[f] += 2 * exceed * m[another];
 88                 updateFatherOf(f, 2 * exceed * m[another]);
 89             }
 90         }  
 91     }
 92 };
 93 
 94 int main()
 95 {
 96     Solution s;
 97     int a[] = {2, 4, 6, 8};
 98 
 99     vector<int> vec(a, a + sizeof(a)/sizeof(int));
100     cout << "满足条件的二叉树一共有:" << endl << s.numFactoredBinaryTrees(vec) << endl;
101     return 0;
102 }

 

posted @ 2018-12-27 17:39  小王点点  阅读(310)  评论(0编辑  收藏  举报