Basic Problem
Description
Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7]
![]()
return its level order traversal as:
[
[3],
[9,20],
[15,7]
]
具体详见LeetCode
Analysis
二叉树的特征是按左右两个子树的指针连接在一起的,然后一般的遍历方法有中序遍历、先序遍历、后序遍历,并没有层次遍历,但是,我们可以通过一些数据结构来层次遍历一棵树,这就是用队列实现的广度优先搜索。
一开始先判断该树是否为空,如果不是就把根节点推入到一个指针队列里,然后成为该队列的head,然后当该队列不为空的时候,就把队头拿出来,然后检查它的左右子树,如果不为空就推入队列。一直进行这样的操作,直到队列为空为止。
这样子,整棵树就可以按照一定的层次顺序打印出来,如果要打印具体每个节点的层高,可以在结构体内增设一个level的标记,子树的level就是父亲的level+1,这样就可以知道具体的层高。
这道题比较特殊的是,它的结构体已经给我们定义好了,所以,我们要想办法借助其他方式去分组。在这道题上,我用的是一个数组,按照顺序把层高存在数组里,相同的数值就代表是同一层的节点,该组对应的下标在节点数值的数组里的那些数就要装进一个vector。
code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*> q;
count = 0;
level.push_back(0);
if (root == NULL) return result;
q.push(root);
while (!q.empty()) {
TreeNode* tmp = q.front();
q.pop();
order.push_back(tmp->val);
if (tmp->left != NULL) {
q.push(tmp->left);
level.push_back(level[count]+1);
}
if (tmp->right != NULL) {
q.push(tmp->right);
level.push_back(level[count]+1);
}
count++;
}
int current = 0;
std::vector<int> v;
int len = order.size();
for (int i = 0; i < len; i++) {
if (level[i] == current) {
v.push_back(order[i]);
} else {
result.push_back(v);
v.clear();
v.push_back(order[i]);
current++;
}
}
result.push_back(v);
return result;
}
private:
int count;
vector<int> level;
std::vector<int> order;
};
Complexity
时间复杂度:
O(n)
空间复杂度:
O(n)
Further Thoughts
跟树里和层有关的问题都可以转化成广度优先搜索来处理,但是每一层节点比较多的时候广度优先搜索的效率可能就不太高,当一个网络很大的时候,每一层的遍历会花费比较多,但是这种情况下,广度优先搜索的效率可能会比深度优先搜索要高,所以,要视情况而定。
然后,其实有一些实际问题(或者编出来的实际问题)包了一层外衣,但是实际上还是搜索的问题。
比如:
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]
Return
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
Note:
1. Return an empty list if there is no such transformation sequence.
2. All words have the same length.
3. All words contain only lowercase alphabetic characters.
4. You may assume no duplicates in the word list.
5. You may assume beginWord and endWord are non-empty and are not the same.
这道题看上去就没有我们上一道题那么直观,但是我认为它本质上还是一道广度优先搜索问题,但是,又有一点小区别,因为它的每一个节点可能能访问若干次,所以,其实这道题是要先把它转化成一个图,再将图用邻接矩阵或者邻接链表(在这里邻接链表会更好些)将图之间的连接关系表示出来,然后用BFS处理,注意,结束的条件是,与找到的第一个解的同一层遍历完才结束,因为可能有很多个解,因为是广度优先搜索,我们是按层一层一层搜索下来的,所以第一个解肯定是最优解,另外可能有多个最优解,所以要遍历完同一层之后才算结束。此题还有其他地方需要注意和优化的,但是现在还没有AC,所以还有很多需要以后补充的地方。