题意

给定一个二叉树的bfs序,求每条边两个端点的异或值之和

方法一

我们考虑直接记录i点,与i点的父亲,这样直接计算节点i与其父亲的异或值即可。
因为每个节点有两个儿子,所以每当i+2,他的父亲就会改变(即序号加1)
那么我们就可以按照这个规律维护两个指针计算。

class Solution {
public:
    /**
     * 
     * @param a int整型vector 表示这棵完全二叉树的Bfs遍历序列的结点编号
     * @return long长整型
     */
    long long tree1(vector<int>& a) {
        int fa = 1;
        int son = 2;
        bool turn = false;
        int n = a.size();
        long long ans = 0;
        for (;son <= n;++ son) {
            ans += a [fa - 1] ^ a [son - 1];    //计算两个端点之间的异或值
            turn = !turn;
            if (!turn) {
                ++ fa;    //i+2,所以父亲也改变了。
            }
        }
        return ans;
    }
};

很显然,由于只遍历了一次a,所以时间复杂度和空间复杂度都为图片说明 ,其中n为节点的数量。

方法二(找儿子)

我们考虑每个节点i的连线有哪些?
为了不重复计算,我们只考虑节点i与他的儿子之间的连线。
对于一颗完全二叉树,我们可以知道节点i的左儿子为2i,右儿子为2i+1
图片说明
所以我们可以直接从1-n遍历i,计算i与儿子之间的异或值。

class Solution {
public:
    /**
     * 
     * @param a int整型vector 表示这棵完全二叉树的Bfs遍历序列的结点编号
     * @return long长整型
     */
    long long tree1(vector<int>& a) {
        long long ans = 0;
        int length = a.size();
        for (int i = 1;i <= length;++ i) {
            int l_son = i * 2,r_son = i * 2 + 1;
            if (l_son <= length) {
                ans += a [i - 1] ^ a [l_son - 1];    //左儿子存在,就计算值
            }
            if (r_son <= length) {
                ans += a [i - 1] ^ a [r_son - 1];    //右儿子存在
            }
        }
        return ans;
    }
};

很显然,由于只遍历了一次a,所以时间复杂度和空间复杂度与方法一相同,都为图片说明 ,其中n为节点的数量。