leetcode刷题笔记(一)

首先要明确的是,数据结构是工具,算法是通过合适的工具解决特定问题的方法。
二叉树是最容易培养框架思维的,而且大部分算法技巧,本质上都是树的遍历问题。
二叉树问题基本框架:

void traverse(TreeNode root) {
    // 前序遍历
    traverse(root.left)
    // 中序遍历
    traverse(root.right)
    // 后序遍历
}

LeetCode 124 题,难度 Hard,让你求二叉树中最大路径和
题目具体如下:

给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。
该路径至少包含一个节点,且不一定经过根节点。

初始代码如下:

class Solution {
public:
    int maxPathSum(TreeNode* root) {
    
    }
};

如开篇所提,二叉树问题的核心就在于三种遍历方式,此题也不例外。
根据题意,最大路径可在某一结点折返一次,即最长路径可为:
左子节点->公共父结点->右子节点;
再往下细分,如何选择左子节点和右子结点呢?对于每一个结点而言,我们需要分别其左子树和右子树各自的MaxPath,这样我们就将可能的最长路径抽象为了左子树MaxPath->公共父结点->右子树MaxPath。之后再将这个可能的最长路径与当前最长路径进行比对,保留较大值。典型的后序遍历。
利用后序遍历由叶节点开始遍历每一节点。对于每一结点他都可能成为最大值所经过的结点。
设左子树能提供的大小为pal,右子树为par;
倘若pal<0,则令其等于0,视为无意义;par同理;
则最大可能值为pal+par+root—>val;
其为父节点能做的贡献为max(pal,par)+root—>val;

C++ 实现代码如下:

/**
 * 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:
    int maxPathSum(TreeNode* root) {
        int ans = INT_MIN;
        oneSideMax(root,ans);
        return ans;
    }
    int oneSideMax(TreeNode* root,int &ans) {
        if (root == NULL) return 0;
        int left = max(0, oneSideMax(root->left,ans));
        int right = max(0, oneSideMax(root->right,ans));
        ans = max(ans, left + right + root->val);
        return max(left, right) + root->val;
    }
};

Java代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        oneSideMax(root);
        return res;
    }
    public int oneSideMax(TreeNode root){
        if (root == null) return 0;
        int left = Math.max(oneSideMax(root.left),0);
        int right = Math.max(oneSideMax(root.right),0);
        res = Math.max(left+right+root.val,res);
        return root.val+Math.max(left,right);
    }
}

LeetCode 105 题,难度 Medium,让你根据前序遍历和中序遍历的结果还原一棵二叉树,很经典的问题

前序遍历和中序遍历有如下特征:
在这里插入图片描述

前序中左起第一位肯定是根结点,我们可以据此找到中序中根结点的位置rootin

while (rootin <= inEnd && in[rootin] != pre[preStart]) rootin++;

中序中根结点左边就是左子树结点,右边就是右子树结点,即[左子树结点,根结点,右子树结点],我们就可以得出左子树结点个数为int left = rootin - inStart;
前序中结点分布应该是:[根结点,左子树结点,右子树结点]
根据前一步确定的左子树个数,可以确定前序中左子树结点和右子树结点的范围:
左子树范围:[preStart + 1, preStart + left] 右子树范围:[preStart + 1 + left, preEnd]
我们可以通过递归进行二叉树的创建:
在这里插入图片描述

如果我们要前序遍历生成二叉树的话,下一层递归应该是:
左子树:root->left = pre_order(前序左子树范围,中序左子树范围,前序序列,中序序列);
右子树:root->right = pre_order(前序右子树范围,中序右子树范围,前序序列,中序序列);
每一层递归都要返回当前根结点root
最后一个结点也被接入二叉树之后,通过以下判断,就无须进行遍历了:

if (preStart> preEnd|| inStart> inEnd) return NULL;

C++完整代码如下:

/**
 * 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:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return pre_order(0, inorder.size() - 1, 0, inorder.size() - 1, preorder, inorder);
    }
    
    TreeNode *pre_order(int preStart, int preEnd, int inStart, int inEnd, vector<int> &pre, vector<int> &in) {
    	if (preStart > preEnd || inStart > inEnd) return NULL;
    	TreeNode *root = new TreeNode(pre[preStart]);
    	int rootin = inStart;
    	while (rootin <= inEnd && in[rootin] != pre[preStart]) rootin++;
    	int left = rootin - inStart;
    	root -> left = pre_order(preStart+1, preStart+left, inStart, rootin-1, pre, in);
    	root -> right = pre_order(preStart+1+left, preEnd, rootin+1, inEnd, pre, in);
    	return root;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值