题解 | #判断是不是完全二叉树#
判断是不是完全二叉树
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; }