代码随想录-13day:二叉树2

一、二叉树的层次遍历

根据代码随想录提供的思路,利用队列的特性,进行解决,但是c语言没有队列接口,因此需要用数组去模拟队列的用法,使用过程中,有几个点需要注意下:

1 C语言写的函数,returnSIze和 returnColumnSize分别代表的意思,第一个returnSize代表的是有多少个数组,即有多少层,另一个是指一个层里面,有多少个size,即每一个元素的数量;

2 注意root为空的情况,这个每次都忘;

3 malloc buff有那几部分呢:

1)sizeColumnSize需要一个buff保存每一层的数据;

2)保存节点需要一个buff,用来当做队列,进行出队入队的操作;

3)result结果需要一个二维数组保存,但是申请的是一个指针数组,因此里面的指针还需要malloc buff,用来存每一层的数值。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
 /**
 队列思想
 1 root 入队,size记录,然后才进行节点操作;
 2 size不为空情况下,出队,保存节点的值,然后保存当前节点的left和right(有情况下)
 **/
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    int** result = (int**)malloc(sizeof(int*) * 2010);//超过节点数设置大小
    int result_idx = 0;
    int* NodeArr = (int*)malloc(sizeof(int) * 1);//root 节点
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 2010);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个vlaue**/
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2010);
    for(int i = 0; i < 2010; i++)
    {
        (*returnColumnSizes)[i] = 0;//初始化
    }
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        (*returnColumnSizes)[*returnSize] = queue_size;//每层节点的个数
        int* Arr = (int* )malloc(sizeof(int) * queue_size);
        int arrIdx = 0;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            Arr[arrIdx++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;
            
            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            
            queue_size--;
        }
        result[(*returnSize)++] = Arr;//多少行,就多少个数组
    }

    return result;
}

二、二叉树的层次遍历2

在1的基础上,做下翻转,C语言中写法需要注意:就是对应每一层的size也要转换(一直没看出问题来!!)
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
 void swap(int** arr, int size, int* lenarr)//change 每一层的size
 {
    int left = 0;
    int right = size -1;
    while(left < right)
    {
       int* tmp = arr[right];
       int len_tmp = lenarr[right];

       arr[right] = arr[left];
       lenarr[right] = lenarr[left];

       arr[left] = tmp;
       lenarr[left] = len_tmp;

       left++;
       right--;
    }
 }

int** levelOrderBottom(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    int** result = (int**)malloc(sizeof(int*) * 2010);//超过节点数设置大小
    int result_idx = 0;
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 2010);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个vlue**/
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2010);
    for(int i = 0; i < 2010; i++)
    {
        (*returnColumnSizes)[i] = 0;//初始化
    }
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        (*returnColumnSizes)[*returnSize] = queue_size;//每层节点的个数
        int* Arr = (int* )malloc(sizeof(int) * queue_size);
        int arrIdx = 0;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            Arr[arrIdx++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;
            
            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            
            queue_size--;
        }
        result[(*returnSize)++] = Arr;//多少行,就多少个数组
    }
    swap(result, *returnSize, *returnColumnSizes);
    return result;
}

三、199.二叉树的右视图

思路1:在层序遍历的基础上进行修改,因为已经拿到每一次的数组元素了,右视图,肯定是每一层的数组元素的最大indx对应的value;

 /**思路1: 层序遍历基础上进行操作,因为保留了每一层的数据分布,那么最右的一定是每一层arr的indx最大那个**/
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    int** result = (int**)malloc(sizeof(int*) * 201);//超过节点数设置大小
    int result_idx = 0;
    int* NodeArr = (int*)malloc(sizeof(int) * 1);//root 节点
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 201);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个vlue**/
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2010);
    for(int i = 0; i < 2010; i++)
    {
        (*returnColumnSizes)[i] = 0;//初始化
    }
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        (*returnColumnSizes)[*returnSize] = queue_size;//每层节点的个数
        int* Arr = (int* )malloc(sizeof(int) * queue_size);
        int arrIdx = 0;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            Arr[arrIdx++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;
            
            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            
            queue_size--;
        }
        result[(*returnSize)++] = Arr;//多少行,就多少个数组
    }

    return result;
}


int* rightSideView(struct TreeNode* root, int* returnSize) {
    /**初始化malloc题目上限个数**/
    int* result = (int*)malloc(sizeof(int) * 101);
    int* arrlen = (int*)malloc(sizeof(int) * 101);
    int** array = (int**)malloc(sizeof(int*) * 101);

    for(int i = 0; i < 101; i++)
    {
        array[i] = calloc(101, sizeof(int));
    }
    int returnlen = 0;
    array = levelOrder(root, &returnlen, &arrlen);
    /**获取array数据,找到每个数组 indx最大那个**/
    for(int i = 0; i < returnlen; i++)
    {
        result[i] = array[i][arrlen[i] -1];
    }
    *returnSize = returnlen;
    return result;
}

思路2:还是利用队列的思想,可以思考,每一层都记录了一个size,当size减小到0时候,此时该节点就是要找的右视图节点。

int* rightSideView(struct TreeNode* root, int* returnSize) {
    int* result = (int*)malloc(sizeof(int) * 201);//超过节点数设置大小
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 201);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
       // int arrIdx = 0;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            //result[(*returnSize)++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的右子节点入队列***/            
            if(curNode->left)
            {
                NodeList[queue_right++] = curNode->left;
            }
            if(curNode->right)
            {
                NodeList[queue_right++] = curNode->right;
            }
            queue_size--;
            /**此时代表当前层已经在最后一个节点了**/
            if(queue_size == 0)
            {
                result[(*returnSize)++] = curNode->val;
            }
        }
    }
    return result;

}

四、二叉树的层平均值

思路1依然是在层次遍历基础上进行计算,然后返回平均值

思路2,每次记录curNode的value,去累加到一个sum上,当此层遍历结束后,存下来;

double* averageOfLevels(struct TreeNode* root, int* returnSize) {
    double* result = (double*)malloc(sizeof(double) * 10001);//超过节点数设置大小 2^N -1
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10001);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        double sum = 0.0;
        int single_size = queue_size;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            sum += (double)curNode->val;
            //result[(*returnSize)++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的右子节点入队列***/            
            if(curNode->left)
            {
                NodeList[queue_right++] = curNode->left;
            }
            if(curNode->right)
            {
                NodeList[queue_right++] = curNode->right;
            }
            queue_size--;
        }            
        /**此时代表当前层遍历结束**/
        // printf("sum = %f mum = %d\n", sum, single_size);
        result[(*returnSize)++] = sum/single_size;
    }
    return result; 
}

四、N叉树的层次遍历

N叉树的层次遍历,和二叉树的层次遍历,不同之处在于,N叉树是用一个节点数组从左到右来保存自己的孩子节点,因此使用队列去入队的时候,就使用遍历的方式,相当于从左至右把当前孩子节点入队。

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numChildren;
 *     struct Node** children;
 * };
 */

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
 /**
 思路:根据二叉树的层次遍历,N叉树改变了左右子树,这里需要注意
 **/
int** levelOrder(struct Node* root, int* returnSize, int** returnColumnSizes) {
    int** result = (int**)malloc(sizeof(int*) * 1001);//超过节点数设置大小
    //int result_idx = 0;
    //int* NodeArr = (int*)malloc(sizeof(int) * 1);//root 节点
    struct Node** NodeList = (struct Node**)malloc(sizeof(struct Node*) * 10001);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个vlaue**/
    *returnColumnSizes = (int*)malloc(sizeof(int) * 1001);
    for(int i = 0; i < 1001; i++)
    {
        (*returnColumnSizes)[i] = 0;//初始化
    }
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        (*returnColumnSizes)[*returnSize] = queue_size;//每层节点的个数
        int* Arr = (int* )malloc(sizeof(int) * queue_size);
        int arrIdx = 0;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct Node* curNode = NodeList[queue_left];
            Arr[arrIdx++] = curNode->val;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的孩子节点入队列***/
            for(int i = 0; i < curNode->numChildren; i++)
            {
                NodeList[queue_right++] = curNode->children[i]; 
            }
            // if(curNode->left)
                // NodeList[queue_right++] = curNode->left;
            
            // if(curNode->right)
                // NodeList[queue_right++] = curNode->right;
            
            queue_size--;
        }
        result[(*returnSize)++] = Arr;//多少行,就多少个数组
    }

    return result;
}

五、515 每个树行中找最大值

思路还是在层次遍历基础上,每一层遍历时候,找到每一层的最大值。

 /**每一层遍历,去比较最大值,直到这一层结束**/
int* largestValues(struct TreeNode* root, int* returnSize) {
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10000);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个保存多少行**/
    *returnSize = 0;
    if(root == NULL)
    {
        return NULL;
    }
    //queue_size = queue_right - queue_left;//获取当前queue size
    //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
    //(*returnColumnSizes)[*returnSize] = queue_size;//每层节点的个数
    int* result = (int* )malloc(sizeof(int) * 1000);//2^N = 100000
    int arrIdx = 0;
    int Max = 0;
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        int* Arr = (int* )malloc(sizeof(int) * queue_size);
        int Max_value = INT_MIN;
        while(queue_size > 0)
        {
            /**把当前节点的value放入数组(出队列)**/
            struct TreeNode* curNode = NodeList[queue_left];
            //Arr[arrIdx++] = curNode->val;
            if(Max_value < curNode->val)
            {
                Max_value = curNode->val;
            }
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;
            
            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            
            queue_size--;
        }
        result[(*returnSize)++] = Max_value;//多少行,就多少个数组
    }
    return result;
}

五、116. 填充每个节点的下一个右侧节点指针

 思路:每一层的节点指向下一个节点,因此需要找到当前节点和下一个节点,在处理过程,没有考虑queue size的情况,导致计算当前层的时候,可能访问到其他位置了,如果不限制size大于0情况下去找next node,可能找到的next node就是其他层的节点,也可能没有值。

struct Node* connect(struct Node* root) {
	//int** result = (int**)malloc(sizeof(int*) * 2010);//超过节点数设置大小
    struct Node** NodeList = (struct Node**)malloc(sizeof(struct Node*) * 100000);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个value**/
    int index = 0;
    int *returnSize = &index;
    if(root == NULL)
    {
        return NULL;
    }
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        //struct Node* preNode = (struct Node*)malloc(sizeof(struct Node));
        while(queue_size > 0)
        {
            /**需要保存当前节点**/
            struct Node* curNode = NodeList[queue_left];
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;

            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            queue_size--;
            if(queue_size > 0)
            {
               /**遍历下一个 Node**/
               struct Node* nextNode = NodeList[queue_left];
               curNode->next = nextNode;
            }
            else
            {
                curNode->next = NULL;
            }
        }
        //result[(*returnSize)++] = Arr;//多少行,就多少个数组
    }

    return root;
}

六、117. 填充每个节点的下一个右侧节点指针 II

和上题做法一样

七、104. 二叉树的最大深度

 按照层序遍历来说,如果每一层都能遍历得到,那么层数就是最大的深度

八、111 二叉树最小深度

int minDepth(struct TreeNode* root) {
    struct TreeNode** NodeList = (struct NoTreeNodede**)malloc(sizeof(struct Node*) * 100000);
    int queue_left = 0, queue_right = 0;//一个用于对头移动,一个用于队尾 index
    NodeList[queue_right++] = root;
    int queue_size = 0;
    /**这个用来保存每层多少个value**/
    int index = 0;
    int *returnSize = &index;
    if(root == NULL)
    {
        return 0;
    }
    int depth = 0;
    while(queue_right > queue_left)//队列不为空
    {
        queue_size = queue_right - queue_left;//获取当前queue size
        //printf("size is %d L=%d, R=%d\n", queue_size, queue_left, queue_right);
        //struct Node* preNode = (struct Node*)malloc(sizeof(struct Node));
        bool left_flg = false;
        bool right_flg = false;
       
        while(queue_size > 0)
        {
            /**需要保存当前节点**/
            struct TreeNode* curNode = NodeList[queue_left];
            left_flg = false;
            right_flg = false;
            /**队列indx往前进一**/
            queue_left++;
 
            /**该节点的左右子节点入队列***/
            if(curNode->left)
                NodeList[queue_right++] = curNode->left;
            else
                left_flg = true; 
            if(curNode->right)
                NodeList[queue_right++] = curNode->right;
            else
               right_flg = true;
            //如果当前节点没有左右子孩子,那么终止于此,不要再遍历当前层后面的节点了
            if(left_flg && right_flg)
            {
                break; 
            }
            queue_size--;
        }
        depth++;
        //printf("depth = %d\n", depth);
        //当前层的一个节点无后继孩子,那么就是最短的深度
        if(left_flg && right_flg)
        {
             break; 
        }
          
       
    }

    return depth ;
}

九、翻转二叉树

方法1-递归法

递归时候swap函数需要注意,因为需要指针传递,我们需要更换的是指针,所以参数是指针的指针,才能改变指针;

 /**
 1 递归法: 思路就是翻转左右节点,注意递归三要素

 **/
 void reserve(struct TreeNode** left, struct TreeNode** right)
 {
     struct TreeNode* tmp_node = *right;
     *right  = *left;
     *left  = tmp_node;
 }
struct TreeNode* invertTree(struct TreeNode* root) {
    if(root == NULL)
      return NULL;
    reserve(&(root->left), &(root->right)); 
    invertTree(root->left);
    invertTree(root->right);


    return root;
}

 方法2-迭代法

首先得理清楚前序遍历的流程,然后根据此流程的基础上进行修改:

/**注意:指针传递,才能改变节点的值,即地址值**/
void reserve(struct TreeNode** left, struct TreeNode** right)
 {
     struct TreeNode* tmp_node = *right;
     *right  = *left;
     *left  = tmp_node;
 }
struct TreeNode* invertTree(struct TreeNode* root) {
    /**用数组模拟栈**/
    int stk_base = -1;//栈底位置
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 101);
    NodeList[++stk_base] = root;
    if(root == NULL)
    {
        return NULL;
    }
    /**栈不为空时候**/
    while(stk_base > -1)
    {
        //pop出栈
        struct TreeNode* curNode =  NodeList[stk_base];
        stk_base--;//相当于出栈
   
        reserve(&(curNode->left), &curNode->right);//翻转二叉树
        //把右节点 左节点入栈
        if(curNode->right)
            NodeList[++stk_base] = curNode->right;
        if(curNode->left)
            NodeList[++stk_base] = curNode->left;

    }

    return root;
}

其次,根据层次遍历的思路,来翻转二叉树。

void reserve(struct TreeNode** left, struct TreeNode** right)
 {
     struct TreeNode* tmp_node = *right;
     *right  = *left;
     *left  = tmp_node;
 }
struct TreeNode* invertTree(struct TreeNode* root) {
    /**用数组模拟队列**/
    //int stk_base = -1;//栈底位置
    int q_left = 0, q_right = 0;
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 101);
    NodeList[q_right++] = root;
    if(root == NULL)
    {
        return NULL;
    }
    /**队列不为空时候**/
    while(q_right > q_left)
    {
        int q_size = q_right - q_left;
        while(q_size > 0)
        {
            //出队列
            struct TreeNode* curNode =  NodeList[q_left];
            q_left++;//相当出队列
            reserve(&(curNode->left), &curNode->right);
 
            //把右节点 左节点入队列
            if(curNode->right)
                NodeList[q_right++] = curNode->right;
            if(curNode->left)
                NodeList[q_right++] = curNode->left;
            
            q_size--;
        }

    }

    return root;
}

十、对称二叉树

该题目依然可以用递归和迭代进行解决:

1 递归法:主要是要理清楚return的情况,其一,如果左右子树有一个是空的,那么必然不对称,没必要比较后面的;其二,如果左右子树都是空的,那么可以理解成只有root节点,是对称的,可以返回ture;其三,如果左右子树都存在,那么如果两个的值不相等,也没有必要再比较后面的节点了,可以直接返回。这里去思考的时候,多加了一个else的情况,就是两个节点值相等,返回ture,这里问题点就在于这里返回之后,导致后面节点无法遍历,如果后面不对称,那么会导致结果出错。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 /**递归:需要注意以下几个情况:
 1 二叉树为空
 2 二叉树不对齐
 **/
bool commpre(struct TreeNode* left, struct TreeNode* right)
{
    /**不满足条件的情况**/
    if((left == NULL && right != NULL) || (right == NULL && left != NULL))
    {
        return false;//某一个为空 另一个不为空
    }
    else if(left == NULL && right == NULL)
    {
       /**两个都为空,对称情况 满足**/
       return true;
    }
    else if(left->val != right->val)//两个不为空,且值不等
    {
        return false;
    }
    /**后面不能判断,因为只是当前层结果是对称的,但是如果后面还有节点,那么会直接return,后面无法对比**/
    // else if(left->val == right->val)
    // {
    //     printf("%d - %d\n", left->val, right->val);
    //     return true;
    // }
    bool outside = commpre(left->left, right->right);
    bool intside = commpre(left->right, right->left);
    return outside && intside;
}
bool isSymmetric(struct TreeNode* root) {
    if(!root)
    {
        return true;
    }

    struct TreeNode* left = root->left;
    struct TreeNode* right = root->right;
    bool result = commpre(left, right);

    return result;
}

 2 迭代法:

可以使用队列或者栈的思想,以队列为例:

bool isSymmetric(struct TreeNode* root) {
    /**使用数组迭代**/
    if(root == NULL)
    {
        return true;
    }
    //1.malloc buff保存节点
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 1001);
    int queue_left = 0, queue_right = 0;
    NodeList[queue_right++] = root->left;//保存左节点
    NodeList[queue_right++] = root->right;//保存右节点
    /**队列不为空**/
    while(queue_right > queue_left)
    {
        int queue_size  = queue_right - queue_left;
        while(queue_size > 0)
        {
            /**节点出队列**/
            struct TreeNode* node_left = NodeList[queue_left++];
            struct TreeNode* node_right = NodeList[queue_left++];
            if(!node_left && !node_right)
            {
                //return true;
                //一样的处理 这里不能直接返回,可能开始的节点对称,后面的不对称,要遍历完
                queue_size -=2;//出队
                continue;
            }

            //其中一个不为空
            if(!node_left && node_right || node_left && !node_right)
            {
                return false;
            }

            if(node_left->val != node_right->val)
            { 
                return false;
            }
            /**入队**/
            //先把外围节点对入队
            NodeList[queue_right++] = node_left->left;
            NodeList[queue_right++] = node_right->right;
            //把内侧节点对加入队列
            NodeList[queue_right++] = node_left->right;
            NodeList[queue_right++] = node_right->left;
            queue_size -=2;//出队2个 size需要减去2个
        }
    }
    return true;
}

这里需要注意:和层序遍历区别,层序遍历是每次获取当前节点,但此题目是需要同时获取左右节点;另外,如果左右节点为空,需要把size剪掉,这样满足出队要求,后面再循环判断时候,不会再入队遍历,导致空指针访问出错。

十一、总结

最近关于二叉树的训练,总结下:

1 遍历方式:1)前中后序遍历,即深度优先遍历,可以使用栈的方式进行迭代,但是前中后续迭代方式可能代码无法统一,因此需要加入一个空节点来记录,可以参考代码随想录;

2 层序遍历:使用队列的思想进行遍历,即广度优先遍历。

两种迭代方式,可以对比着学习,便于进一步理解。

除了迭代方式,也可以用递归的方式进行解决,需要注意递归的返回,递归中止条件,以及递归参数等信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值