LeetCode中级算法之树和图
中序遍历二叉树
Question:
给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
Solution:
- 递归算法:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res,res2;
if(root == NULL) return res;
res = inorderTraversal(root -> left);
res.push_back(root -> val);
res2 = inorderTraversal(root -> right);
res.insert(res.end(), res2.begin(), res2.end());
return res;
}
二叉树的锯齿形层次遍历
Question:
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层次遍历如下:
[
[3],
[20,9],
[15,7]
]
Solution:
采用栈结构,用flag来记录当前的方向,如果上一层是按从左到右的方向入栈的,那么出栈正好是从右向左,flag记录此时方向向左,那么应该先入右子树,再入左子树:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
bool flag = false; //true represents right direction;
vector<vector<int>> res;
vector<int> temp;
stack<TreeNode*> q1;
if(!root) return res;
q1.push(root);
while(!q1.empty())
{
stack<TreeNode*> q2;
while(!q1.empty())
{
temp.push_back(q1.top()->val);
if(flag)
{
if(q1.top() -> right) q2.push(q1.top()->right);
if(q1.top() -> left) q2.push(q1.top()->left);
q1.pop();
}
else
{
if(q1.top() -> left) q2.push(q1.top()->left);
if(q1.top() -> right) q2.push(q1.top()->right);
q1.pop();
}
}
res.push_back(temp);
temp.clear();
flag = !flag;
q1 = q2;
}
return res;
}
从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
Solution:
前序遍历先访问根节点,因此前序遍历序列的第一个字母肯定就是根节点,由于中序遍历先访问左子树,再访问根节点,最后访问右子树,所以我们找到中序遍历中根节点的位置,然后左边就是左子树,右边→_→就是右子树。
这时候找到了递归的入口,子递归将中序遍历的数组分为左右两部分,分别调用递归函数往下进行构造:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int i;
TreeNode* res;
if(preorder.empty()) return NULL;
res = new TreeNode(preorder[0]);
if(preorder.size() == 1) return res;
for(i = 0; i < inorder.size(); i++)
if(inorder[i] == preorder[0]) break;
vector<int> il(inorder.begin(),inorder.begin() + i);
vector<int> ir(inorder.begin() + i + 1,inorder.end());
vector<int> pl(preorder.begin() + 1,preorder.begin() + i + 1);
vector<int> pr(preorder.begin() + i + 1,preorder.end());
res -> left = buildTree(pl,il);
res -> right = buildTree(pr,ir);
return res;
}
填充每个节点的下一个右侧节点指针
Question:
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
Solution:
我直接按上道题思路做的,很简单:
Node* connect(Node* root) {
if(root == NULL) return NULL;
queue<Node*> q1;
Node* suzy;
q1.push(root);
while(!q1.empty())
{
queue<Node*> q2;
while(!q1.empty()){
suzy = q1.front();
q1.pop();
if(!q1.empty())
suzy -> next = q1.front();
if(suzy -> left) q2.push(suzy -> left);
if(suzy -> right) q2.push(suzy -> right);
}
q1 = q2;
}
return root;
}
二叉搜索树中第K小的元素
Question:
给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 1
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
输出: 3
进阶:
如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化 kthSmallest 函数?
Solution:
我直接用到了前面中序遍历的代码,第k个出栈的结果就是查找结果。
int kthSmallest(TreeNode* root, int k) {
int i = 0;
stack<TreeNode*> mystack;
TreeNode* node = root;
while(node || !mystack.empty())
{
if(node != NULL)
{
mystack.push(node);
node = node -> left;
}
else
{
node = mystack.top();
i++;
if(i == k) return node -> val;
mystack.pop();
node = node -> right;
}
}
return 0;
}
岛屿数量
Question:
给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
Solution:
思路就是广度或者深度优先遍历,我本来用的队列,迭代去做,但是超时了:
int numIslands(vector<vector<char>>& grid) {
queue<int> q;
int xs = grid.size();
if(xs == 0) return 0;
int ys = grid[0].size();
int count = 0;
for(int i = 0; i < xs; i++)
{
for(int j = 0; j < ys; j++)
{
if(grid[i][j] == '1')
{
q.push(i);
q.push(j);
while(!q.empty())
{
int x = q.front();
q.pop();
int y = q.front();
q.pop();
grid[x][y] = '0';
if(x > 0 && grid[x - 1][y] == '1')
{
q.push(x-1);
q.push(y);
}
if(x < xs - 1 && grid[x + 1][y] == '1')
{
q.push(x+1);
q.push(y);
}
if(y < ys - 1 && grid[x][y + 1] == '1')
{
q.push(x);
q.push(y+1);
}
if(y > 0 && grid[x][y - 1] == '1')
{
q.push(x);
q.push(y-1);
}
}
count++;
}
}
}
return count;
}
改为用迭代做,可以了:
int numIslands(vector<vector<char>>& grid) {
if(grid.empty() || grid[0].empty()) return 0;
int m = grid.size(), n = grid[0].size(), res=0;
vector<vector<bool>> visited(m, vector<bool>(n, false));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]=='1' && !visited[i][j]){
DFS(grid, visited, i, j);
res++;
}
}
}
return res;
}
void DFS(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y){
if(x<0 || x>=grid.size()) return;
if(y<0 || y>=grid[0].size()) return;
if(grid[x][y]!='1' || visited[x][y]) return;
visited[x][y]=true;
DFS(grid, visited, x-1, y);
DFS(grid, visited, x+1, y);
DFS(grid, visited, x, y-1);
DFS(grid, visited, x, y+1);
}
这段代码是转载的,原文: https://blog.csdn.net/x603560617/article/details/88169732 ,不过这道题为什么用迭代会超时我还是有点不理解,或许是我的代码有问题吧。。希望大神指点~~~