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 ,不过这道题为什么用迭代会超时我还是有点不理解,或许是我的代码有问题吧。。希望大神指点~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值