leetcode热题100刷题笔记(2)

每日一题:543.二叉树的直径

在这里插入图片描述

思路

这道题很容易看出来可以用dfs解决,但是其中有一个容易迷惑的点,就是所谓的“最长路径”并不一定经过根节点!
因此,我们需要在dfs的过程中,对每一个节点,计算其左子树的高度L以及右子树的高度R,那么以当前节点为起点的路径,经过的节点的最大值就是L+R+1,并且不断的去更新最大值。
而路径的长度就是节点数减去1,因此最后返回ans-1;

代码

/**
 * 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 ans=1;
    int dfs(TreeNode* root){
        if(root==NULL) return 0;
        //记录以左孩子为根的子树的高度
        int left = dfs(root->left);
        //记录以右孩子为根的子树的高度
        int right = dfs(root->right);
        ans=max(ans,left+right+1);
        return max(left,right)+1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        dfs(root);
        return ans-1;
    }
};

62.不同路径

在这里插入图片描述

思路

此类简化版本的迷宫问题,一上手首先想到的就是dfs,并且它的决策树也是只有两个分支,因此十分简单
但是此题用dfs会超时,所以想到使用动态规划的方法,定义一个二维动态规划数组dp,dp[i][j]表示以(i,j)作为终点时,可以选择的最大路径树,由于只能向右或者向下,显而易见,状态转移方程:

dp[i][j] = dp[i-1][j]+dp[i][j-1];

代码

递归版本(会超时):

class Solution {
public:
    int ans=0;
    void dfs(int m,int n,int a,int b){
        if(a==m&&b==n){
            ans++;
            return;
        }
        if(a<=m&&b<=n){
            dfs(m,n,a+1,b);
            dfs(m,n,a,b+1);
        }   
        else
            return;
    }
    int uniquePaths(int m, int n) {
        dfs(m,n,1,1);
        return ans;
    }
};

动态规划版本:

class Solution {
public:
    int uniquePaths(int m, int n) {
        int dp[m][n];
        for(int i=0;i<n;i++)
            dp[0][i]=1;
        for(int i=0;i<m;i++)
            dp[i][0]=1;
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

64.最小路径和

在这里插入图片描述

显而易见的一道动态规划题目,没啥可说的

代码

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int m=grid.size(),n=grid[0].size();
        int dp[m][n];
        dp[0][0]=grid[0][0];
        for(int i=1;i<n;i++){
            dp[0][i]=dp[0][i-1]+grid[0][i];
        }
        for(int i=1;i<m;i++){
            dp[i][0]=dp[i-1][0]+grid[i][0];
        }
        for(int i =1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j]=min(dp[i-1][j],dp[i][j-1]) + grid[i][j];
            }
        }
        return dp[m-1][n-1];
    }
};

70.爬楼梯

在这里插入图片描述

思路

每次爬一个或两个台阶,可以看成是决策树的分叉,写出dfs的代码并不困难,但是依然会超时,进而考虑动态规划,定义一维数组dp,dp[i]表示当高度为i时爬到顶楼的方法数,而到达i层,可以从i-2层爬两层,也可以从i-1层爬一层,所以状态转移方程:

dp[i]=dp[i-1]+dp[i-2];

代码

暴力递归(会超时)

class Solution {
public:
    int ans=0;
    void dfs(int n,int cur){
        if(cur>n) return;
        if(cur==n){
            ans++;
            return;
        }
        dfs(n,cur+1);
        dfs(n,cur+2);
    }
    int climbStairs(int n) {
        dfs(n,0);
        return ans;
    }
};

动态规划

class Solution {
public:
    int climbStairs(int n) {
        int dp[n+1];
        dp[0]=dp[1]=1;
        for(int i=2;i<=n;i++)
            dp[i]=dp[i-2]+dp[i-1];
        return dp[n];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值