LeetCode——Subtree of Another

来源:互联网 发布:lua保存数据 编辑:程序博客网 时间:2024/05/22 17:26

LeetCode——Subtree of Another

# 572
Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree s could also be considered as a subtree of itself.

Example 1:
Given tree s:

     3    / \   4   5  / \ 1   2

Given tree t:

   4   / \ 1   2

Return true, because t has the same structure and node values with a subtree of s.

Example 2:
Given tree s:

     3    / \   4   5  / \ 1   2    /   0

Given tree t:

   4  / \ 1   2

Return false.

这题的目的是判断一个数是否是另一棵树的子数。从第二个例子可以看出,子树必须是完整的,不能是中间一部分,必须是叶节点。
这题显然可以用递归写,大部分树的问题,都可以用递归的方法解决。其实和前面写过的一题对称树也没大多差别。代码也很容易懂,递归的话,多使用的话,理清思路,就很容易掌握了。

  • 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:    bool isSubtree(TreeNode* s, TreeNode* t) {        if(!s)             return false;        if(is_Sub(s,t))             return true;        return isSubtree(s -> left,t) || isSubtree(s -> right,t);        }    bool is_Sub(TreeNode* s,TreeNode* t){        if( !s && !t)            return true;        if( !s || !t)            return false;         if(s -> val != t -> val)            return false;        return is_Sub(s -> left,t -> left) && is_Sub(s -> right,t -> right);                   }     };
  • Java
/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */class Solution {    public boolean isSubtree(TreeNode s, TreeNode t) {        if (s == null)              return false;          if (isSame(s, t))              return true;          return isSubtree(s.left, t) || isSubtree(s.right, t);      }    private boolean isSame(TreeNode s, TreeNode t) {          if (s == null && t == null)              return true;          if (s == null || t == null)              return false;        if (s.val != t.val)              return false;          return isSame(s.left, t.left) && isSame(s.right, t.right);      }}
  • Python
**# Definition for a binary tree node.# class TreeNode(object):#     def __init__(self, x):#         self.val = x#         self.left = None#         self.right = Noneclass Solution(object):    def isSubtree(self, s, t):        """        :type s: TreeNode        :type t: TreeNode        :rtype: bool        """        if not s or not t: return not s and not t        if self.check(s, t): return True        return self.isSubtree(s.left, t) or self.isSubtree(s.right, t)    def check(self, s, t):        if not s or not t: return not s and not t        if s.val != t.val: return False        return self.check(s.left, t.left) and self.check(s.right, t.right)**

看到其他一些人的解法,有一种思路是对s和t两棵树分别进行序列化,各生成一个字符串,如果t的字符串是s的子串的话,就说明t是s的子树。其中一个注意的地方是,为了避免前缀,在每个节点值前面都加一个字符。代码如下。

  • 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:    bool isSubtree(TreeNode* s, TreeNode* t) {        ostringstream os1, os2;  //构造一个字符串,使用ostringstream类,该类能够根据内容自动分配内存        serialize(s, os1);        serialize(t, os2);        return os1.str().find(os2.str()) != string::npos;//    }    void serialize(TreeNode* node, ostringstream& os) { //这里的序列化使用的是前序遍历        if (!node) os << ",#";        else {            os << "," << node->val;            serialize(node->left, os);            serialize(node->right, os);        }    }};

npos可以表示string的结束位子,是string::type_size 类型的,也就是find()返回的类型。find函数在找不到指定值得情况下会返回string::npos
关于ostringstream类,也简单的描述一下。
C++提供的流(stream)包括三种类型:用于控制台输入/输出的流、用于文件操作的文件流和用于字符串处理的字符串流。

(1) 基于控制台的流

istream:用于从流中读取内容;

ostream:用于将内容写到数据流中;

iostream:用于对流进行读写,从istream和ostream派生;

它们包含在iostream头文件中。

(2) 用于文件读取/写入的文件流

ifstream:用于从文件中读取,由istream派生而来;

ofstream:用于将内容写到文件中去,由ostream派生而来;

fstream:实现文件的读写操作,有iostream派生而来;

它们包含在头文件fstream中。

(3) 基于字符串I/O操作的字符串流

istringstream:实现从字符串(string)对象中读取内容,由istream派生而来;

ostringstream:实现将内容写到字符串(string)对象中,由ostream派生而来;

stringstream:实现string对象的读写操作,由iostream派生而来;

它们包含在头文件sstream中。

这种解法的Python写法

  • Python
# Definition for a binary tree node.# class TreeNode(object):#     def __init__(self, x):#         self.val = x#         self.left = None#         self.right = Noneclass Solution(object):    def isSubtree(self, s, t):        """        :type s: TreeNode        :type t: TreeNode        :rtype: bool        """        def preorder(node):            if not node:                return "$"            return "^" + str(node.val) + "#" + preorder(node.left) + preorder(node.right)        print preorder(s)        print preorder(t)        return preorder(t) in preorder(s)

还看到一种解法,使用了hash树,运行时间非常的短。但相对复杂一点,记录下来,学习一下。

  • Python
# Definition for a binary tree node.# class TreeNode(object):#     def __init__(self, x):#         self.val = x#         self.left = None#         self.right = Nonefrom hashlib import md5class Solution(object):    def isSubtree(self, s, t):        def treehash(root):            h = md5(treehash(root.left) + str(root.val) + treehash(root.right)).hexdigest() if root else ''            hashes.append(h)            return h        hashes = []        h = treehash(t)        hashes = []        treehash(s)        return h in hashes    def isSubtree(self, s, t):        def string(root):            return '(%d,%s,%s)' % (root.val, string(root.left), string(root.right)) if root else ''        return string(t) in string(s)    def isSubtree(self, s, t):        def tuplify(root):            return (root.val, tuplify(root.left), tuplify(root.right)) if root else None        return str(tuplify(t)) in str(tuplify(s))