LeetCode刷题又一天(六)

在这里插入图片描述

简单题·合并二叉树

题目

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。

你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

示例 1:

输入: 
	Tree 1                     Tree 2                  
          1                         2                             
         / \                       / \                            
        3   2                     1   3                        
       /                           \   \                      
      5                             4   7                  
输出: 
合并后的树:
	     3
	    / \
	   4   5
	  / \   \ 
	 5   4   7

注意: 合并必须从两个树的根节点开始。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-binary-trees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路

这还要什么思路,这不是很简单吗?
以一棵树为主,另一棵树为辅,辅树直接贴到主树上去。主树有的节点,辅树节点加进去,主树没有的节点,辅树直接整个贴上去。

然后,我就发现我忘了递归该怎么写了。。。
好尴尬啊。


代码实现

TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
    if (t1 == nullptr) {
        return t2;
    }
    if (t2 == nullptr) {
        return t1;
    }
    t1->val += t2->val;
    t1->left = mergeTrees(t1->left, t2->left);
    t1->right = mergeTrees(t1->right, t2->right);
    return t1;
}

简单题·翻转二叉树

如题


思路

还要思路吗?写了上一题,递归算是想起来一点。其实主要就是那个return,到底要不要return有点晕。


代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }

        TreeNode* temp = root->left;
        root->left = root->right;
        root->right = temp;
        
        invertTree(root->left);   
        invertTree(root->right);
        
        return root;
    }
};

简单题·找到所有数组中消失的数字

题目

给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[5,6]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路

思路一:话不多说,直接上流程。
1、指针指向第一个位置,将数取出,放到数值对应的位置。并将那个位置的数放到当前位置来。
2、[4,3,2,7,8,2,3,1] ->[7,3,2,4,8,2,3,1]
3、[7,3,2,4,8,2,3,1] ->[3,3,2,4,8,2,7,1]
4、[3,3,2,4,8,2,7,1] ->[2,3,3,4,8,2,7,1]
5、[2,3,3,4,8,2,7,1] ->[3,2,3,4,8,2,7,1]
6、这时候,本来应该将第一个位置的3放到第3个位置,但是第三个位置已经有主了,所以将第一个位置置为0
7、[3,2,3,4,8,2,7,1]->[0,2,3,4,8,2,7,1]
8、指针后移一个位置
9、发现第二个位置的值等于2,于是再后移;同理,再后移;再后移。现在指向第五个位置了
10、[0,2,3,4,8,2,7,1] ->[0,2,3,4,1,2,7,8]
11、[0,2,3,4,1,2,7,8] ->[1,2,3,4,0,2,7,8]
12、由于当前指针指向了0,所以指针后移
13、当前位置是2,但是第二个位置已经被占用,当前位置清0,指针后移。
14、后移,再后移,到尾了。
15、最终结果:[1,2,3,4,0,0,7,8]

16、再次遍历数组,纪录数据为0的位置,分别是第五个位置和第六个位置,于是返回[5,6]

看着是很繁琐,但是其实只遍历了两次,不要被事物的表面现象所迷惑。


代码实现

vector<int> findDisappearedNumbers(vector<int>& nums) {
        int sz = nums.size();
        int temp = 0;
        vector<int> ret;

        for(int i = 0;i<sz;){
            if((i+1) == nums[i] || nums[i] == 0){
                i++;
                continue;
            }

            temp = nums[i]-1;
            if(nums[temp] == nums[i]){  //出现了重合
                nums[i] = 0;
                i++;
                continue;
            }
            nums[i] = nums[temp];
            nums[temp] = temp+1;
        }

        for(int j = 0;j<sz;j++){
            if(nums[j] == 0)
                ret.push_back(j+1);
        }
        return ret;
    }

思路二

优化一下上面的方法,其实还有更直观的。
我为什么要互换呢?我把值取出来不就得了吗?

1、指针指向第一个位置,取出第一个位置的值,第一个位置清0
2、[4,3,2,7,8,2,3,1] ->[0,3,2,7,8,2,3,1],value = 4,keep_value = value
3、取出第4个位置的值,将4填进去:value = nums[3],nums[3] = keep_value,keep_value = value;
4、[0,3,2,4,8,2,3,1],value = 7
5、[0,3,2,4,8,2,7,1],3
6、[0,3,3,4,8,2,7,1],2
7、[0,2,3,4,8,2,7,1],3
8、发现原有位置现在有主了,指针后移。
9、跟思路一一样,一路移到第五个位置。
10、[0,2,3,4,0,2,7,1],value = 8
11、[0,2,3,4,0,2,7,8],1
12、[1,2,3,4,0,2,7,8],又结束了,指针再往后
13、[1,2,3,4,0,0,7,8],有主了,指针再往后
14、到尾了,结束了。
15、再遍历一遍,取出0的位置。


这样就比较容易看出来是遍历了两遍了吧。


简单题·二叉树的直径

我要去吃早饭了,就长话短说吧。

题目

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :
给定二叉树

  1
 / \
2   3

/ \
4 5

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

注意:两结点之间的路径长度是以它们之间边的数目表示。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

以前做过,放弃了,其实现在想想,思路也很直接。就是每个节点,左右子树的最大深度,加上它自己是一个节点。那么以某节点为中枢的长度就出来了。

然后对每个节点都这样算一下,并拿一个全局(类对象)当标兵即可。


代码实现

class Solution {
    
    int ans;

    int depth(TreeNode* rt){
        if (rt == NULL) {
            return 0; // 访问到空节点了,返回0
        }
        int L = depth(rt->left); // 左儿子为根的子树的深度
        int R = depth(rt->right); // 右儿子为根的子树的深度
        ans = max(ans, L + R + 1); // 计算d_node即L+R+1 并更新ans
        return max(L, R) + 1; // 返回该节点为根的子树的深度
    }

public:
    int diameterOfBinaryTree(TreeNode* root) {
        ans = 1;
        depth(root);
        return ans - 1;
    }
};

就酱,吃饭。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值