LeetCode刷题day34

简介: LeetCode刷题day34

今日刷题重点—二叉树的对称性

226. 翻转二叉树

翻转一棵二叉树

示例:

输入:
     4
   /   \
  2     7
 / \   / \
1   3 6   9
输出:
     4
   /   \
  7     2
 / \   / \
9   6 3   1

思路分析

反转二叉树:

7a55829528004e19bf80aedd274ca7dd.png

本质就是:把每一个结点的左右孩子互换一下,除了叶子结点所有的都要进行这样的操作.

方法一:递归法(以先序为例)

递归三要素


递归参数:每次要交换的根节点(交换的是其左右节点)

结束条件:当root为null时.

确定单层递归的逻辑

因为是先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。


image.gif

参考代码1

//递归 
TreeNode* invertTree(TreeNode* root) {
  if(root==NULL) {
    return NULL;
  }
  swap(root->left,root->right);
  invertTree(root->left);
  invertTree(root->right);
  return root;
}

迭代法1(栈模拟)

用栈来模拟,因为递归的底层使用的就是栈.

参考代码2

//迭代法
TreeNode* invertTree(TreeNode* root) {
  if(root==NULL) {
    return NULL;
  }
  stack<TreeNode*> tab;
  tab.push(root);
  while(!tab.empty()) {
    TreeNode* node = tab.top();//中
    tab.pop();
    swap(node->left,node->right);
    if(node->left!=NULL) { //右
      tab.push(node->left);
    }
    if(node->right!=NULL) { //左
      tab.push(node->right);
    }
  }
  return root;
}

迭代法2(队列模拟)

用层次遍历的思路也是可以的.

参考代码3

TreeNode* invertTree(TreeNode* root) {
  if(root==NULL) {
    return NULL;
  }
  queue<TreeNode*> Q;
  Q.push(root);
  while(!Q.empty()) {
    int size = Q.size();
    for(int i = 0;i<size;i++){
      TreeNode* node = Q.front();
      Q.pop();
      swap(node->left,node->right);
      if(node->left){
        Q.push(node->left);
      }
      if(node->right){
        Q.push(node->right);
      }
    }
  }
  return root;
}

注意: 递归的中序遍历是不行的,因为使用递归的中序遍历,某些节点的左右孩子会翻转两次。

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1
   / \
  2   2
   \   \
   3    3

思路分析

首先要清楚对称二叉树比较的是哪两个节点,要比较的可不是左右节点!

对于是否对称,要比较的是根节点的左右子树是否可以反转. 理解了这一点就知道,其实我们要比较的是两棵树,所以在递归遍历过程中要同时遍历这两棵树.


那么如何进行比较呢?

如下图,我们只需要外侧和外侧进行对比,内侧和内侧进行比较即可.

e4ebe59202d3407c8492ce61f69e0e1a.png

方法一:递归

递归三部曲:

  • 确定参数和返回值:参数是左右子树,返回值是bool
  • 确定终止条件

首先要把两个节点为空的情况弄清楚! 否则后面比较数值的时候就会操作空指针了。


节点为空的情况有:


左节点为空,右节点不为空,不对称,return false

左不为空,右为空,不对称 return false

左右都为空,对称,返回true

左右节点不为空:


左右都不为空,比较节点数值,不相同就return false

剩下的一种情况就是,左右节点都不为空,而且其节点值相等.(我们后序在处理)


//先进行判空操作
  if(!left&&right || left&&!right) {
    return false;
  }
  if(!left&&!right) {
    return true;
  }
  //在进行 根节点值不同的情况
  if(left->val!=right->val) {
    return false;
  }
  • 确定单层递归的逻辑

单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。

  • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
  • 比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
  • 如果左右都对称就返回true ,有一侧不对称就返回false 。
//当前两个根节点的值相同,开始比较其树上的其他节点
  bool outSide = isCompare(left->left,right->right);
  bool inSide = isCompare(left->right,right->left);
  return outSide&&inSide;

参考代码1

//递归..
bool isCompare(TreeNode* left,TreeNode* right) {
  //先进行判空操作
  if(!left&&right || left&&!right) {
    return false;
  }
  if(!left&&!right) {
    return true;
  }
  //在进行 根节点值不同的情况
  if(left->val!=right->val) {
    return false;
  }
  //当前两个根节点的值相同,开始比较其树上的其他节点
  bool outSide = isCompare(left->left,right->right);
  bool inSide = isCompare(left->right,right->left);
  return outSide&&inSide;
}
bool isSymmetric(TreeNode* root) {
  if(root==NULL) {
    return true;
  }
  return isCompare(root->left,root->right);
}

方法二: 迭代法(使用队列)

可以使用队列来判断左右节点及其子树是否对称.

image.gif


参考代码2

bool isSymmetric(TreeNode* root) {
  if(root==NULL){
    return true;
  } 
  queue<TreeNode*> Q;
  Q.push(root->left);
  Q.push(root->right);
  while(!Q.empty()){
    TreeNode* node1 = Q.front();
    Q.pop();
    TreeNode* node2 = Q.front();
    Q.pop();
    //进行判空操作
    if(node1&&!node2 || !node1&&node2){
      return false;
    } 
    if(!node1&&!node2){//都为空说明是对称的,继续往下判断. 
      continue;
    }  
    if(node1->val!=node2->val){
      return false;
    }
    //说明此刻当前俩节点值相等,继续判断其树上的节点是否相等. 
    Q.push(node1->left);
    Q.push(node2->right);
    Q.push(node1->right);
    Q.push(node2->left); 
  }
  return true; 
}

方法三:使用栈

方法二,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。

参考代码3

bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        stack<TreeNode*> st; // 这里改成了栈
        st.push(root->left);
        st.push(root->right);
        while (!st.empty()) {
            TreeNode* leftNode = st.top(); st.pop();
            TreeNode* rightNode = st.top(); st.pop();
            if (!leftNode && !rightNode) {
                continue;
            }
            if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
                return false;
            }
            st.push(leftNode->left);
            st.push(rightNode->right);
            st.push(leftNode->right);
            st.push(rightNode->left);
        }
        return true;
    }

100. 相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:


image.jpeg

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

image.jpeg

输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:


8fcab70d767c4ba4a8e260e0d4d3242a.jpg

输入:p = [1,2,1], q = [1,1,2]
输出:false

思路分析

上题是对称,这个题是相等,只需要修改下比较的两个节点的顺序即可.

也有递归,迭代(通过队列),迭代(通过栈)

参考代码1

bool isSameTree(TreeNode* left, TreeNode* right) {
  //先进行判空操作
  if(!left&&right || left&&!right) {
    return false;
  }
  if(!left&&!right) {
    return true;
  }
  //在进行 根节点值不同的情况
  if(left->val!=right->val) {
    return false;
  }
  //当前两个根节点的值相同,开始比较其树上的其他节点
  bool outSide = isSameTree(left->left,right->left);
  bool inSide = isSameTree(left->right,right->right);
  return outSide&&inSide;
}

参考代码2

bool isSameTree(TreeNode* left, TreeNode* right) {
  //先进行判空操作
  if(!left&&right || left&&!right) {
    return false;
  }
  if(!left&&!right) {
    return true;
  }
  //在进行 根节点值不同的情况
  if(left->val!=right->val) {
    return false;
  }
  //当前两个根节点的值相同,开始比较其树上的其他节点
  bool outSide = isSameTree(left->left,right->left);
  bool inSide = isSameTree(left->right,right->right);
  return outSide&&inSide;
}

572. 另一棵树的子树


给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。


二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。


示例 1:


9859b16b97a24393bf9b208b6420bb90.jpg

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:

23f71dab30b14e5e91fd8520ede87da4.jpg

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

思路分析

这个题判断两个树是否是树A和子树B的关系.

只需要遍历A上的每一个子树,判断和B是否相等,如果相等,则返回true.当A上的所有结点遍历完了还没找到则说明不存在,返回false.

参考代码

bool isSameTree(TreeNode* left, TreeNode* right) {
  //先进行判空操作
  if(!left&&right || left&&!right) {
    return false;
  }
  if(!left&&!right) {
    return true;
  }
  //在进行 根节点值不同的情况
  if(left->val!=right->val) {
    return false;
  }
  //当前两个根节点的值相同,开始比较其树上的其他节点
  bool outSide = isSameTree(left->left,right->left);
  bool inSide = isSameTree(left->right,right->right);
  return outSide&&inSide;
}
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
  if(root==NULL){//我 root树都已经遍历完了还没找到则直接返回false 
    return false;
  }
  //进行递归判断,只要有一个为真即为真. 
  return isSameTree(root,subRoot)||isSameTree(root->left,subRoot) ||isSameTree(root->right,subRoot);
}
相关文章
|
28天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
50 6
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
43 4
|
2月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
99 2
|
28天前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
2月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
47 7
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
22 4
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
48 5
|
2月前
|
算法 Python
【Leetcode刷题Python】 LeetCode 2038. 如果相邻两个颜色均相同则删除当前颜色
本文介绍了LeetCode 2038题的解法,题目要求在一个由'A'和'B'组成的字符串中,按照特定规则轮流删除颜色片段,判断Alice是否能够获胜,并提供了Python的实现代码。
45 3
|
2月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
21 3