题解 | #判断是不是完全二叉树#

判断是不是完全二叉树

https://www.nowcoder.com/practice/8daa4dff9e36409abba2adbe413d6fae

版本1:

1、先把二叉树层序遍历出来,元素放到一个二维数组里面

2、通过判断每一层元素的个数是否 == 2^h

3、再判断最后一层是否全在左边,这里用到了一个一维数组,判断第一个为空的是否出现在了不为空的元素前,如果出现了就不是完全二叉树

function isComplete(root) {
    if(!root) return true;

    // 层序遍历
    const queue = [], res = [], isAllLeft = [];

    queue.push(root);

    while(queue.length) {
        let size = queue.length;

        const temp = [];
        while(size--) {
            const cur = queue.shift();
            temp.push(cur.val);

            if(cur.left) {
                isAllLeft.push(cur.left.val)
                queue.push(cur.left);
            } else {
                isAllLeft.push('#');
            }
            if(cur.right) {
                isAllLeft.push(cur.right.val);
                queue.push(cur.right);
            } else {
                isAllLeft.push('#');
            }

        }
        res.push(temp);
    }
    
    let ohterLevel = true, len = res.length;
    // 判断除h层外,其它各层的结点数是否都达到最大个数
    for(let i = 0; i < len - 1; i++) {
        if(res[i].length != Math.pow(2, i)) {
            ohterLevel = false;
        }
    }
    let h = true, firstNull, lastNotNull;
    // 判断最后一层是否全部集中在左边
    for(let i = 0; i < isAllLeft.length; i++) {
        const temp = isAllLeft[i];
        if(temp === '#' && !firstNull) {
            firstNull = i;
        }
        if(temp != '#') {
            lastNotNull = i;
        }
    }
    if(firstNull < lastNotNull) h = false;

    return ohterLevel && h;
}

module.exports = {
    isCompleteTree : isCompleteTree
};

上面的代码是第一次写的时候,陷入的误区。虽然也能AC,但是多用了一个二维数组,多做了第二步的判断。

于是有了下面版本2的写法:

直接层序遍历,将元素全部放到一个一维数组 isAllLeft 里面包括为空的,最后判断第一个为空的是否出现在了不为空的前面

function isComplete(root) {
    if(!root) return true;

    // 层序遍历
    const queue = [], isAllLeft = [];

    queue.push(root);

    while(queue.length) {
        let size = queue.length;
        while(size--) {
            const cur = queue.shift();
            if(cur != null) {
                isAllLeft.push(cur.val);
            } else {
                isAllLeft.push('#');
                continue;
            }

            queue.push(cur.left);
            queue.push(cur.right);
        }
    }

    let h = true, firstNull, lastNotNull;

    for(let i = 0; i < isAllLeft.length; i++) {
        const temp = isAllLeft[i];
        if(temp === '#' && !firstNull) {
            firstNull = i;
        }
        if(temp != '#') {
            lastNotNull = i;
        }
    }
    if(firstNull < lastNotNull) h = false;

    return h;
}

版本2的思路是对的,但是代码还是不够简洁。不必使用一个一维数组去存储所有的结点元素,

1、可以借助一个标记位来标记第一个出现的叶子结点,

2、如果在后续的结点遍历中遇到了不是叶子结点的结点,就可以判断这棵树不是完全二叉树了。

就是完全二叉树的特性:

层序遍历完全二叉树,中途不会出现叶子结点。

function isCompleteTree( root ) {
    if(!root) return true;

    const queue = [];
    queue.push(root);
    let firstNullFlag = false;
    let cur;
    while(queue.length) {
        cur = queue.shift();
        // 标记第一个出现为空的叶子结点
        if(cur == null) {
            firstNullFlag = true;
            continue;
        }
        // 后续遍历,如果前面出现了叶子结点,就不是完全二叉树了
        if(firstNullFlag) {
            return false;
        }

        queue.push(cur.left);
        queue.push(cur.right);
    }
    return true;
}

全部评论

相关推荐

头像
11-21 11:39
四川大学 Java
是红鸢啊:忘了还没结束,还有字节的5k 违约金
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务