【LeetCode111-120】很多道二叉树的问题(左右顺序很重要),一道hard DP题,两道杨辉三角以及一道DP三角

本文探讨了多种二叉树相关算法问题,包括求最短路径长度、路径查找、树形结构调整、序列化等问题,并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

111.返回二叉树最短长度【easy】

例如【1,2】的长度为2!!也就是node到最近的叶子的长度

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(!root)return 0;
        if(!root->left)return 1+minDepth(root->right);
        if(!root->right)return 1+minDepth(root->left);
        return min(minDepth(root->left),minDepth(root->right))+1;
    }
};


112.判断从根到叶有没有何为sum的一条路径

注意【】,0返回的是false....所有对于空要单独判断下

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(!root)return false;
        if(!root->left&&!root->right){if(sum==root->val)return true;return false;}
        if(!root->left)return hasPathSum(root->right,sum-root->val);
        if(!root->right)return hasPathSum(root->left,sum-root->val);
        if(hasPathSum(root->right,sum-root->val))return true;
        if(hasPathSum(root->left,sum-root->val))return true;
        return false;
    }
};

别人的思路一样但简洁了很多的方法:

bool hasPathSum(TreeNode *root, int sum) {
        if (root == NULL) return false;
        if (root->val == sum && root->left ==  NULL && root->right == NULL) return true;
        return hasPathSum(root->left, sum-root->val) || hasPathSum(root->right, sum-root->val);
    }


113.输出所有根到叶和为sum的路径

在112基础上迭代一下……记得temp要pop...

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>>result;
        vector<int>temp;
        help(result,temp,root,sum);
        return result;
    }
    void help(vector<vector<int>>&result,vector<int>&temp,TreeNode* root,int sum){
        if(!root)return;
        temp.push_back(root->val);
        if(!root->left&&!root->right&&root->val==sum){
            result.push_back(temp);
        }
        if(root->left){help(result,temp,root->left,sum-root->val);temp.pop_back();}
        if(root->right){help(result,temp,root->right,sum-root->val);temp.pop_back();}
        return;
    }
};


114.二叉树转化为单链表【medium】

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / \
       2   5
      / \   \
     3   4   6

The flattened tree should look like:
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

root->left=nullptr;一定要加上!!!不然会报错double free....因为左侧和右侧都指向了同一个……


class Solution {
public:
    void flatten(TreeNode* root) {
        //
        if(!root)return;
            flatten(root->left);
            TreeNode* temp=root->right;
            root->right=root->left;
            root->left=nullptr;//一定要加上!!不然报double free...
          //  TreeNode* temp2=root;
            while(root->right){
                root=root->right;//并不一定要保证root指针一定要指向开头(检测机制还是很强大的)
            }
            root->right=temp;
            flatten(root->right);
    }

};


115.S删去几个字符转化为T的种数【hard】

Given a string S and a string T, count the number of distinct subsequences of T in S.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

Here is an example:
S = "rabbbit"T = "rabbit"

Return 3.



DP问题

dp[i][j]代表t的前i+1位被s的前j+1位弄出来的个数

如果t[i]和s[j]相等,那么dp[i][j]=dp[i][j-1]+dp[i-1][j-1];

否则dp[i][j]=dp[i][j-1];

数学归纳法……也就是DP……

class Solution {
public:
	int numDistinct(string s, string t) {
		//试试DP
		if(s.empty()&&t.size()>0)return 0;
		if(t.empty())return 1;
		
		vector<vector<int>>dp(t.size(), vector<int>(s.size(), 0));
		//行数代表T,列数代表S
		if (s[0] == t[0])dp[0][0] = 1;
		for (int i = 1; i<s.size(); ++i) { if (s[i] == t[0])dp[0][i] = dp[0][i - 1] + 1; else dp[0][i] = dp[0][i - 1]; }
		//列不用管了,都是0
		for (int i = 1; i<t.size(); ++i) {
			for (int j = 1; j<s.size(); ++j) {
				if (t[i] == s[j]) {
					dp[i][j] = dp[i][j-1] + dp[i - 1][j - 1];
				}
				else dp[i][j] = dp[i][j - 1];
			}
		}
		return dp[t.size() - 1][s.size() - 1];
	}
};


116.把二叉树同层的串起来【medium】

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

For example,
Given the following perfect binary tree,

         1
       /  \
      2    3
     / \  / \
    4  5  6  7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL
击败了90%的人…

/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        //迭代…可以用一个的尽量用一个,不然要花更多时间
        if(!root||!root->left)return;//因为正好是完全二叉树……
        root->left->next=root->right;
        if(root->next)root->right->next=root->next->left;//这一行很关键…把两棵子树串起来了
        connect(root->left);
        connect(root->right);
        return;
    }
};

117.上一题加强版,任意二叉树同级串起来

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

  • You may only use constant extra space.

For example,
Given the following binary tree,

         1
       /  \
      2    3
     / \    \
    4   5    7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \    \
    4-> 5 -> 7 -> NULL

这题调bug调了很久…………


最后发现应该先connect右边再左边,不然上一行还没遍历完,缺少next信息!!!

class Solution {
public:
	void connect(TreeLinkNode *root) {
		if (!root)return;
		if (!root->left && !root->right)return;
		if (root->left) {
			if (root->right) {
				root->left->next = root->right;
				TreeLinkNode *temp = root;
				while (temp->next) {
					if (temp->next->left) { root->right->next = temp->next->left; break; }
					else if (temp->next->right) { root->right->next = temp->next->right; break; }
					temp = temp->next;
				}
/*先右再左非常非常非常关键!!!不然下一行运行的时候缺少上方的next信息,先右边就没问题了……*/
				connect(root->right);
				connect(root->left);
			}
			else {
				TreeLinkNode *temp = root;
				while (temp->next) {
					if (temp->next->left) { root->left->next = temp->next->left; break; }
					else if (temp->next->right) { root->left->next = temp->next->right; break; }
					temp = temp->next;
				}
				connect(root->left);
			}
		}
		else if (root->right) {
			TreeLinkNode *temp = root;
			while (temp->next) {
				if (temp->next->left) { root->right->next = temp->next->left; break; }
				else if (temp->next->right) { root->right->next = temp->next->right; break; }
				temp = temp->next;
			}
			connect(root->right);
		}

		return;
	}
};

118.杨辉三角的实现(帕斯卡三角)

Given numRows, generate the first numRows of Pascal's triangle.

For example, given numRows = 5,
Return

[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        //杨辉三角,数字等于上一行俩相加
        vector<vector<int>>result;
        if(numRows==0)return result;
        result.push_back({1});
        for(int i=2;i<=numRows;++i)help(result,i);
        return result;
        
    }
    void help(vector<vector<int>>&result,int n){
        vector<int>temp(n,1);
        for(int i=1;i<n-1;++i){
            temp[i]=result.back()[i]+result.back()[i-1];
        }
        result.push_back(temp);
    }
};


119.输出杨辉三角第k+1行

O(n),空间利用最低,击败了80%…

从{1}不断迭代到最终结果,空间利用率应该接近最高了

class Solution {
public:
    vector<int> getRow(int k) {
       vector<int>temp(1,1);
       for(int i=2;i<=k+1;++i){
           temp.push_back(1);
           int help=1;
           for(int j=1;j<i-1;++j){
               temp[j]=temp[j]+help;
               help=temp[j]-help;
           }
       }
       return temp;
    }
};


120.三角形vector里找到和最小的从上到下的路径


直观上第一感觉是迭代,果然42/43,代码如下:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        return minimumTotal(triangle,0,0,0);
    }
    int minimumTotal(vector<vector<int>>& triangle,int m,int n,int result){
        if(m==triangle.size())return result;
        return min(minimumTotal(triangle,m+1,n,result+triangle[m][n]),minimumTotal(triangle,m+1,n+1,result+triangle[m][n]));
    }
};
接着试了试DP(题目里只允许用O(n)空间)

然后发现可以只用了O(1)空间

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        for(int i=1;i<triangle.size();++i){
            triangle[i][0]+=triangle[i-1][0];
            for(int j=1;j<triangle[i-1].size();++j){
                triangle[i][j]+=min(triangle[i-1][j],triangle[i-1][j-1]);
            }
            triangle[i].back()+=triangle[i-1].back();
        }
        int result=2147483647;
        for(auto ii:triangle.back()){
            result=min(ii,result);
        }
        return result;
        
    }

};
继而看了下别人的方法,发现可以由下而上!!简直机智……

简洁了很多,而且计算量降低了…

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
       //再试试自下而上
        for(int i=triangle.size()-2;i>=0;--i){
            for(int j=0;j<triangle[i].size();++j){
                triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]);
            }
        }
        return triangle[0][0];
    }

};



祝刷题愉快~~







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱铭德

五毛也是爱٩(●´৺`●)૭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值