重温hot100-day5
41. 102 二叉树层序遍历
简单的层序遍历。利用队列实现即可,可以去刷刷代码随想录,有关层序遍历的各种变形应用有很多,挺不错的。
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;vector<vector<int>> result;if(!root)return result;que.push(root);int size = que.size();while(!que.empty()){vector<int> n;for(int i=0; i<size; i++){TreeNode* temp = que.front();if(temp->left)que.push(temp->left);if(temp->right)que.push(temp->right);n.emplace_back(temp->val);que.pop();}result.emplace_back(n);size = que.size();}return result;}
};
42 108. 将数组元素转换为二叉树
递归思想,每次给中间值构建节点,然后左右子树分别调用构建函数,传入一个数组区间
class Solution {
public:TreeNode* build(vector<int>& nums, int left, int right){if(left > right)return nullptr;int mid = left+(right-left)/2;TreeNode* node = new TreeNode(nums[mid]);node->left = build(nums, left, mid-1);node->right = build(nums, mid+1, right);return node;}TreeNode* sortedArrayToBST(vector<int>& nums) {TreeNode* result = build(nums, 0, nums.size()-1);return result;}
};
43 98. 验证二叉搜索树
本质是中序遍历的应用,但中序遍历把所有值保存,再判断,太麻烦了,计较就是在遍历的时候直接进行对比,利用一个指向前一个节点的pre指针,每次都将当前节点和pre节点值进行对比,如果>=,则就说明不满足递增条件,直接返回false即可
class Solution {
public:TreeNode* pre = NULL; // 用来记录前一个节点bool isValidBST(TreeNode* root) {if (root == NULL) return true;bool left = isValidBST(root->left);if (pre != NULL && pre->val >= root->val) return false;pre = root; // 记录前一个节点bool right = isValidBST(root->right);return left && right;}
};
44 230. 二叉搜索树中第K小的元素
中序遍历,保存结构,直接返回num[k-1]即可
class Solution {
public:vector<int> nums;void travel(TreeNode* root){if(!root)return;travel(root->left);nums.emplace_back(root->val);travel(root->right);}int kthSmallest(TreeNode* root, int k) {travel(root);return nums[k-1];}
};
45. 二叉树的右视图
层序遍历的应用,每次只保存队列中最后一个元素。对应还有个左视图,只保留第一个元素
class Solution {
public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*> que;vector<int> result;if(root == NULL)return result;que.push(root);while(!que.empty()){int size = que.size();for(int i =0;i<size;i++){TreeNode* t = que.front();if(i == size-1)result.emplace_back(t->val);if(t->left) que.push(t->left);if(t->right) que.push(t->right);que.pop();}}return result;}
};
46. 二叉树展开为链表
直接的方法就是先利用先序遍历求得数组,再利用数组构建单链表。每次左子树为null。递归构建就好
class Solution {
public:vector<int> nums;void travel(TreeNode* node){if(!node)return;nums.emplace_back(node->val);travel(node->left);travel(node->right);}TreeNode* build(int left, int right){if(left>right)return nullptr;TreeNode* node = new TreeNode(nums[left]);cout<<left<<" "<<right<<endl;node->left = NULL;node->right = build(left+1, right);return node;}void flatten(TreeNode* root) {travel(root);for(auto i:nums)cout<<i<<" ";cout<<endl;if(!root)return;root->left = NULL;root->right = build(1, nums.size()-1);}
};
47. 105 从前序与中序遍历序列构造二叉树
经典题,关键在于,前序遍历得到中间节点。利用该节点将中序遍历分成两个子数组。在根据中序遍历数组中找该mid。这样获得两个孩子结点的中序遍历结果,根据长度分割前序遍历,在得到两个孩子节点的前序遍历。然后递归构造即可
class Solution {
public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(preorder.size() == 0)return nullptr;TreeNode* node = new TreeNode(preorder[0]);int mid = 0;while(mid<inorder.size() && inorder[mid] != preorder[0]){// cout<<mid<<endl;mid++;}vector<int> left(inorder.begin(), inorder.begin()+mid);vector<int> right(inorder.begin()+mid+1, inorder.end());int temp = left.size();vector<int> left_pre(preorder.begin()+1, preorder.begin()+1+temp);vector<int> right_pre(preorder.begin()+1+temp, preorder.end());node->left = buildTree(left_pre, left);node->right = buildTree(right_pre, right);return node;}
};
48. 437 路径之和Ⅲ
挺难想的递归。因为不一定从根节点开始,因此对每个节点都要进行一次递归查找,递归函数中又是递归
class Solution {
public:int travel(TreeNode* root, long targetSum){if(!root)return 0;// if(targetSum == 3)// cout<<root->val<<endl;int result = 0;if(root->val == targetSum){result++;// cout<<targetSum<<endl;}result += travel(root->left, targetSum-root->val);result += travel(root->right, targetSum-root->val);return result;}int pathSum(TreeNode* root, int targetSum) {if(!root)return 0;int result = travel(root, targetSum);result += pathSum(root->left, targetSum);result += pathSum(root->right, targetSum);return result;}
};
49. 236 二叉树的最近公共祖先
递归思想,如果左右子树都查到了结果,说明两个目标左右各一个,那么目前root就是结果。如果左子树没有结果,那就说明两个值都在右子数。这样递归
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root== p || root==q || root==NULL) return root;TreeNode* left = lowestCommonAncestor(root->left, p, q);TreeNode* right = lowestCommonAncestor(root->right, p,q);if(left && right)return root;if(!left) return right;return left;}
};
50. 124 二叉树中的最大路径和
这道题有难度的,很不好想到,跟那个二叉树的直径一个道理。关键在于想到,每个节点的路径最大值来源,要么是以根节点为连接点的左+根节点+右,要么是纯左+根/右+根。temp表示已有的最大路径和,每次不断更新即可
class Solution {
public:int depth(TreeNode* root, int &temp){if(!root)return 0 ;int left = depth(root->left, temp); //左最大和int right = depth(root->right, temp); //右最大和int a = root->val + max(0, left) + max(0, right); //拼在一起的最大和int b = root->val + max(0, max(left, right)); //单支+根节点的最大和。temp = max(temp, max(a, b)); //temp表示原始最大路径,本次结果的两种情况ab中选最大的,再更新tempreturn b;}int maxPathSum(TreeNode* root) {int result = INT_MIN;depth(root, result);return result;}
};