树与二叉树——练习题

  • 深度优先遍历(借用栈)

    • 前序遍历(递归法,迭代法)

    • 中序遍历(递归法,迭代法)

    • 后序遍历(递归法,迭代法)

  • 广度优先遍历(借用队列)

    • 层次遍历(迭代法)

递归三步曲:

  • 「确定递归函数的参数和返回值:」确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型
  • 「确定终止条件:」写完了递归算法,  运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出
  • 「确定单层递归的逻辑:」确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程

1. 二叉树的前序遍历✌

代码实现:递归 + 迭代

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
#define MAX_NODE 100

// 递归
void pre_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) { // 终止条件
        return;
    }
    res[(*returnSize)++] = root->val;
    pre_order(root->left, res, returnSize);
    pre_order(root->right, res, returnSize);
}

// 迭代(非递归) 深度优先搜索---借用栈
void pre_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) {
        return;
    }
    struct TreeNode *stack[MAX_NODE];
    int top = -1;
    stack[++top] = root;
    // 栈先进后出,前序遍历:根—左—右   右子树先进栈
    while (top != -1) { // 栈不为空则执行while循环
        struct TreeNode *p = stack[top]; // 记录栈顶
        top--;
        res[(*returnSize)++] = p->val;
        if (p->right) { // 右子树进栈
            stack[++top] = p->right;
        }
        if (p->left) { // 左子树进栈
            stack[++top] = p->left;
        }
    }
}

int* preorderTraversal(struct TreeNode *root, int *returnSize) {
    int *res = malloc(sizeof(int) * MAX_NODE);
    *returnSize = 0;
    pre_order(root, res, returnSize);
    return res;
}

2. 二叉树的中序遍历✌

代码实现:递归 + 迭代

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
#define MAX_NODE 100

// 递归
void mid_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) { // 终止条件
        return;
    }
    mid_order(root->left, res, returnSize);
    res[(*returnSize)++] = root->val;
    mid_order(root->right, res, returnSize);
}

// 迭代(非递归) 深度优先搜索---借用栈
void mid_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) {
        return;
    }
    struct TreeNode *stack[MAX_NODE]; // 定义一个栈
    int top = -1; // 栈顶
    struct TreeNode *p = root;
    struct TreeNode *q = NULL;
    while (p || top != -1) {
		if (p) { // 一直往左走
			stack[++top] = p;
			p = p->left;
		} else {
			q = stack[top]; // 记录栈顶
            top--; // 出栈
			res[(*returnSize)++] = q->val;
			p = q->right; // 右子树
		}
	}
}

int* inorderTraversal(struct TreeNode *root, int *returnSize) {
    int *res = malloc(sizeof(int) * MAX_NODE);
    *returnSize = 0;
    mid_order(root, res, returnSize);
    return res;
}

3. 二叉树的后序遍历✌

代码实现:递归 + 两种迭代方法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

#define MAX_NODE 100

// 递归
void post_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) { // 终止条件
        return;
    }
    post_order(root->left, res, returnSize);
    post_order(root->right, res, returnSize);
    res[(*returnSize)++] = root->val;
}

// 迭代(非递归) 深度优先搜索---借用栈
/*
第一种方法:
    先序遍历是 中左右 --->调整代码左右循序--->中右左--->反转result数组--->左右中
    后序遍历是 左右中
*/
void post_order(struct TreeNode *root, int *res, int *returnSize) {
    if (root == NULL) {
        return;
    }
    struct TreeNode *stack[MAX_NODE]; // 创建一个栈
    int top = -1; // 栈顶
    stack[++top] = root;
    while (top != -1) { // 栈不为空则执行while循环
        struct TreeNode *node = stack[top]; // 记录栈顶
        res[(*returnSize)++] = node->val;
        top--;
        if (node->left) { // 左子树先进栈
            stack[++top] = node->left;
        }
        if (node->right) { // 右子树进栈
            stack[++top] = node->right;
        }
    }
    // 反转res数组
    // int i = 0, j = *returnSize - 1;
    // while (i < j) {
    //     int temp = res[i];
    //     res[i] = res[j];
    //     res[j] = temp;
    //     i++;
    //     j--;
    // }
    for (int i = 0; i < *returnSize / 2; i++) {
        int temp = res[i];
        res[i] = res[*returnSize - 1 - i];
        res[*returnSize - 1 - i] = temp;
    }
}

/*
第二种方法:
    1、沿着根的左孩子,依次入栈,直到左孩子为空
    2、读栈顶元素进行判定,若右孩子不空且未被访问,将右孩子执行第一步
    3、栈顶元素出栈
*/
void post_order(struct TreeNode *root, int *res, int *returnSize) {
    struct TreeNode *stack[MAX_NODE]; // 创建一个栈
    int top = -1; // 栈顶 
    struct TreeNode *p = root, *r = NULL; // r标记最近访问过的结点
	while (p || top != -1) {
		if (p) { // 一直往左走
			stack[++top] = p;
			p = p->left;
		} else {
			p = stack[top];
			// 获取栈顶元素赋值给p
			// ❤case one❤
			if (p->right && p->right != r) { // 若右孩子存在且未被访问
				p = p->right; // 就让右孩子
				stack[++top] = p; // 入栈
				p = p->left; // 让右孩子向左
				// 上面三句意思就是让右孩子的左孩子一直入栈,一直向左走
			} else {
			    // ❤case two❤
                res[(*returnSize)++] = stack[top--]->val; // 右孩子为空或未被访问过,就出栈
				r = p;  // r标记最近访问结点
				p = NULL;  // r置空
				// 置空原因:因为这个结点已经出栈了
			}
		}
	}
}

int* postorderTraversal(struct TreeNode *root, int *returnSize) {
    int *res = malloc(sizeof(int) * MAX_NODE);
    *returnSize = 0;
    post_order(root, res, returnSize);
    return res;
}

4. 二叉树的层序遍历

代码实现:

/**
 * 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().
 */
// returnColumnSizes:用于存储每个数组中元素个数
int** levelOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) {
    *returnSize = 0;
    if (root == NULL) {
        return NULL;
    }
    int **res = (int**)malloc(sizeof(int*) * 2000);
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2000);
    struct TreeNode *queue[2001]; // 创建一个队列  注意:队头不放元素,长度须+1
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int colSize = 0, last = tail; // 队头 - 队尾 = 每一层结点个数
        res[*returnSize] = (int*)malloc(sizeof(int) * (last - head));
        while (head < last) {
            struct TreeNode *node = queue[++head];
            res[*returnSize][colSize++] = node->val;
            if (node->left != NULL) { // 左子树入队列
                queue[++tail] = node->left;
            }
            if (node->right != NULL) { // 右子树入队列
                queue[++tail] = node->right;
            }       
        }
        (*returnColumnSizes)[*returnSize] = colSize;
        (*returnSize)++;
    }
    return res;
}

5. 二叉树的层序遍历 ||

思路:相对于102.二叉树的层序遍历,就是最后把res数组反转一下就可以了

/**
 * 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().
 */
// returnColumnSizes:用于存储每个数组中元素个数
int** levelOrderBottom(struct TreeNode *root, int *returnSize, int **returnColumnSizes) {
    *returnSize = 0;
    if (root == NULL) {
        return NULL;
    }
    int **res = (int**)malloc(sizeof(int*) * 2000);
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2000);
    struct TreeNode *queue[2001]; // 创建一个队列 注意:队头不放元素,长度须+1
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int colSize = 0, last = tail;
        res[*returnSize] = (int*)malloc(sizeof(int) * (last - head));
        while (head < last) {
            struct TreeNode *node = queue[++head];
            res[*returnSize][colSize++] = node->val;
            if (node->left) { // 左子树入队列
                queue[++tail] = node->left;
            }
            if (node->right) { // 右子树入队列
                queue[++tail] = node->right;
            }       
        }
        (*returnColumnSizes)[*returnSize] = colSize;
        (*returnSize)++;
    }

    // 反转res数组
    // 动态开辟一个二维数组ret
    int **ret = (int**)malloc(sizeof(int*) * (*returnSize));
    // 保存res每行的大小(数组元素个数)
    int nums[*returnSize];
    for (int i = 0; i < *returnSize; i++) {
        nums[i] = (*returnColumnSizes)[i];
    }
    // 反转returnColumnSizes数组
    for (int i = 0; i < *returnSize; i++) {
        (*returnColumnSizes)[i] = nums[*returnSize - i - 1];
    }
    // 反转res到ret中
    for (int i = 0; i < *returnSize; i++) {
        ret[i] = (int*)malloc(sizeof(int) * (*returnColumnSizes)[i]);
        for (int j = 0; j < nums[*returnSize - i - 1]; j++) {
            ret[i][j] = res[*returnSize - i - 1][j];
        }
    }
    // free
    for (int i = 0; i < *returnSize; i++) {
        free(res[i]);
    }
    free(res);
    return ret;
}

6. 二叉树的右视图

思路:层序遍历的时候,判断是否遍历到单层的最后一个元素,如果是,就放进result数组中,随后返回result就可以了

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* rightSideView(struct TreeNode *root, int *returnSize) {
    int *ret = malloc(sizeof(int) * 100);
    memset(ret, 0, sizeof(int) * 100);
    *returnSize = 0;
    if (root == NULL) {
        return ret;
    }
    struct TreeNode *queue[101]; // 创建一个队列
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int last = tail;
        while (head < last) {
            struct TreeNode *node = queue[++head];
            if (head == last) {
                ret[(*returnSize)++] = node->val;
            }
            if (node->left) {
                queue[++tail] = node->left;
            }
            if (node->right) {
                queue[++tail] = node->right;
            }
        }
    }
    return ret;
}

7. 二叉树的层平均值

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
double* averageOfLevels(struct TreeNode *root, int *returnSize) {
    double *ret = malloc(sizeof(double) * 10000);
    memset(ret, 0, sizeof(int) * 10000);
    *returnSize = 0;
    if (root == NULL) {
        return ret;
    }
    struct TreeNode *queue[10001]; // 创建一个队列
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int last = tail;
        double sum = 0;
        int size = tail - head; // 每层结点个数
        while (head < last) {
            struct TreeNode *node = queue[++head];
            sum += node->val;
            if (node->left) {
                queue[++tail] = node->left;
            }
            if (node->right) {
                queue[++tail] = node->right;
            }
        }
        ret[(*returnSize)++] = sum / size;
    }
    return ret;
}

8. 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().
 */
int** levelOrder(struct Node *root, int *returnSize, int **returnColumnSizes) {
    int **res = malloc(sizeof(int*) * 1000);
    *returnSize = 0;
    *returnColumnSizes = (int*)malloc(sizeof(int) * 10000);
    if (root == NULL) {
        return res;
    }
    struct Node *queue[10001]; // 创建一个队列  注意:队头不放元素,长度须+1
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int colSize = 0, last = tail;
        res[*returnSize] = (int*)malloc(sizeof(int) * (last - head));
        while (head < last) {
            struct Node *node = queue[++head];
            res[*returnSize][colSize++] = node->val;
            for (int i = 0; i < node->numChildren; i++) {
                queue[++tail] = node->children[i];
            }
        }
        (*returnColumnSizes)[*returnSize] = colSize;
        (*returnSize)++;
    }
    return res;
}

9. 在每个树行中找最大值

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* largestValues(struct TreeNode *root, int *returnSize) {
    int *res = malloc(sizeof(int*) * 10000);
    *returnSize = 0;
    if (root == NULL) {
        return res;
    }
    struct TreeNode *queue[10001]; // 创建一个队列  注意:队头不放元素,长度须+1
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    int max;
    while (head < tail) {
        int last = tail;
        max = queue[tail]->val;
        while (head < last) {
            struct TreeNode *node = queue[++head];
            if (node->val > max) {
                max = node->val;
            }
            if (node->left) {
                queue[++tail] = node->left;
            }
            if (node->right) {
                queue[++tail] = node->right;
            }
        }
        res[(*returnSize)++] = max;
    }
    return res;
}

10. 填充每个节点的下一个右侧节点指针

代码实现:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *left;
 *     struct Node *right;
 *     struct Node *next;
 * };
 */

struct Node* connect(struct Node *root) {
	if (root == NULL) {
        return NULL;
    }
    struct Node *queue[4096];
    int head = 0, tail = 0;
    queue[++tail] = root;
    while (head < tail) {
        int last = tail;
        struct Node *pre = NULL;
        while (head < last) {
            struct Node *p = queue[++head];
            if (pre == NULL) {
                pre = p;
            } else {
                pre->next = p;
                pre = p;
            }
            if (head == last) { // 处理每层最后一个结点
                p->next = NULL;
            }
            if (p->left) {
                queue[++tail] = p->left;
            }
            if (p->right) {
                queue[++tail] = p->right;
            }
        }
    }
    return root;
}

11. 翻转二叉树

思路:

  • 在翻转时,需要从根节点往下先交换左右子树,然后再递归到左右子树进行相同的操作

(先序遍历 and 层序遍历)

  • 在翻转时,需要从下往上先交换左右子树,然后再递归到父节点进行交换(后序遍历)
  • 中序遍历不可以(原因:先翻转左子树, 然后左右子树交换,这时候再翻转的右子树是之前的左子树,最后相当于将root左右子树交换)

层序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

// 交换左右子树 —— 改变指向
void swap(struct TreeNode *root) {
    struct TreeNode *l = root->left;
    struct TreeNode *r = root->right;
    root->left = r;
    root->right = l;
}

struct TreeNode* invertTree(struct TreeNode *root) {
    if (root == NULL) {
        return root;
    }
    struct TreeNode *queue[101]; // 创建一个队列
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        struct TreeNode *node = queue[++head];
        swap(node); // 翻转
        if (node->left) {
            queue[++tail] = node->left;
        }
        if (node->right) {
            queue[++tail] = node->right;
        }
    }
    return root;
}

先序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
#define MAX_NODE 100

// 交换左右子树
void swap(struct TreeNode *root) {
    struct TreeNode *l = root->left;
    struct TreeNode *r = root->right;
    root->left = r;
    root->right = l;
}

// 递归:先序遍历
// void pre_order(struct TreeNode *root) {
//     if (root == NULL) {
//         return;
//     }
//     swap(root); // 交换
//     pre_order(root->left);
//     pre_order(root->right);
// }

// 迭代(非递归) 深度优先搜索---借用栈
void pre_order(struct TreeNode *root) {
    if (root == NULL) {
        return;
    }
    struct TreeNode *stack[MAX_NODE];
    int top = -1;
    stack[++top] = root;
    // 栈先进后出,前序遍历:根—左—右   右子树先进栈
    while (top != -1) { // 栈不为空则执行while循环
        struct TreeNode *r = stack[top]; // 记录栈顶
        top--;
        swap(r);
        if (r->right) { // 右子树进栈
            stack[++top] = r->right;
        }
        if (r->left) { // 左子树进栈
            stack[++top] = r->left;
        }
    }
}

struct TreeNode* invertTree(struct TreeNode *root) {
    if (root == NULL) {
        return root;
    }
    pre_order(root);
    return root;
}

后序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
#define MAX_NODE 100

// 交换左右子树
void swap(struct TreeNode *root) {
    struct TreeNode *l = root->left;
    struct TreeNode *r = root->right;
    root->left = r;
    root->right = l;
}

// 递归:后序遍历
// void post_order(struct TreeNode *root) {
//     if (root == NULL) {
//         return;
//     }
//     post_order(root->left);
//     post_order(root->right);
//     swap(root); // 交换
// }

/*
第二种方法:迭代
    1、沿着根的左孩子,依次入栈,直到左孩子为空
    2、读栈顶元素进行判定,若右孩子不空且未被访问,将右孩子执行第一步
    3、栈顶元素出栈
*/
void post_order(struct TreeNode *root) {
    struct TreeNode *stack[MAX_NODE]; // 定义一个栈
    int top = -1; // 栈顶 
    struct TreeNode *p = root, *r = NULL; // r标记最近访问过的结点
	while (p || top != -1) {
		if (p) { // 一直往左走
			stack[++top] = p;
			p = p->left;
		} else {
			p = stack[top];
			// 获取栈顶元素赋值给p
			// ❤case one❤
			if (p->right && p->right != r) { // 若右孩子存在且未被访问
				p = p->right; // 就让右孩子
				stack[++top] = p; // 入栈
				p = p->left; // 让右孩子向左
				// 上面三句意思就是让右孩子的左孩子一直入栈,一直向左走
			} else {
			    // ❤case two❤
                struct TreeNode *node = stack[top];
                top--;
                swap(node);
				r = p;  // r标记最近访问结点
				p = NULL;  // r置空
				// 置空原因:因为这个结点已经出栈了
			}
		}
	}
}

struct TreeNode* invertTree(struct TreeNode *root) {
    if (root == NULL) {
        return root;
    }
    post_order(root);
    return root;
}

12. 对称二叉树

分析比较的是两个子树的里侧和外侧的元素是否相等

本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool compare(struct TreeNode *l, struct TreeNode *r) {
    // 首先排除空节点的情况
    if (l == NULL && r != NULL) {
        return false;
    } else if (l != NULL && r == NULL) {
        return false;
    } else if (l == NULL && r == NULL) {
        return true;
    } else if (l->val != r->val) { // 排除了空节点,再排除数值不相同的情况
        return false;
    }

    // 此时就是:左右节点都不为空,且数值相同的情况
    // 此时才做递归,做下一层的判断
    return compare(l->left, r->right) && compare(l->right, r->left);
}
 
bool isSymmetric(struct TreeNode *root) {
    if (root == NULL) {
        return true;
    }
    return compare(root->left, root->right);
}

13. 二叉树的最大深度

后序遍历通过递归函数的返回值做计算树的高度

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define max(a, b) ((a) > (b) ? (a) : (b))

int getDepth(struct TreeNode *node) {
    if (node == NULL) {
        return 0;
    }
    int leftDepth = getDepth(node->left); // 左
    int rightDepth = getDepth(node->right); // 右
    int depth = 1 + max(leftDepth, rightDepth); // 中
    return depth;
}

int maxDepth(struct TreeNode *root) {
    return getDepth(root);
}

精简代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define max(a, b) ((a) > (b) ? (a) : (b))

int maxDepth(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    return 1 + max(maxDepth(root->left), maxDepth(root->right));
}

先序遍历:深度优先遍历——回溯

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int result;

void getDepth(struct TreeNode *node, int depth) {
    result = depth > result ? depth : result; // 根

    if (node->left == NULL && node->right == NULL) {
        return;
    }

    // 左
    if (node->left) {
        depth++; // 深度+1
        getDepth(node->left, depth);
        depth--; // 回溯,深度-1
    }
    // 右
    if (node->right) {
        depth++; // 深度+1
        getDepth(node->right, depth);
        depth--; // 回溯,深度-1
    }
}

int maxDepth(struct TreeNode *root) {
    result = 0;
    if (root == NULL) {
        return result;
    }
    getDepth(root, 1);
    return result;
}

层序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int maxDepth(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    int depth = 0;
    struct TreeNode *queue[10001];
    int head = 0;
    int tail = 0;
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int last = tail;
        depth++;
        while (head < last) {
            struct TreeNode *node = queue[++head];
            if (node->left) {
                queue[++tail] = node->left;
            }
            if (node->right) {
                queue[++tail] = node->right;
            } 
        }
    }
    return depth;
}

14. N叉树的最大深度

代码实现:

后序遍历:超时

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numChildren;
 *     struct Node** children;
 * };
 */
#define max(a, b) ((a) > (b) ? (a) : (b))

int maxDepth(struct Node *root) {
    if (root == 0) {
        return 0;
    }
    int depth = 0;
    for (int i = 0; i < root->numChildren; i++) {
        depth = max(depth, maxDepth(root->children[i]));
    }
    return depth + 1;
}

层序遍历:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numChildren;
 *     struct Node** children;
 * };
 */
#define max(a, b) ((a) > (b) ? (a) : (b))

int maxDepth(struct Node *root) {
    if (root == NULL) {
        return 0;
    }
    int depth = 0;
    struct Node *queue[10001]; // 创建一个队列  注意:队头不放元素,长度须+1
    int head = 0; // 队头
    int tail = 0; // 队尾
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int last = tail;
        depth++;
        while (head < last) {
            struct Node *node = queue[++head];
            for (int i = 0; i < node->numChildren; i++) {
                queue[++tail] = node->children[i];
            }
        }
    }
    return depth;
}

15. 二叉树的最小深度

注意:最小深度是从根节点到最近叶子节点的最短路径上的节点数量(左右孩子都为空的节点才是叶子节点!)

后序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define min(a, b) ((a) > (b) ? (b) : (a))

int getDepth(struct TreeNode *node) {
    if (node == NULL) {
        return 0;
    }
    int leftDepth = getDepth(node->left); // 左
    int rightDepth = getDepth(node->right); // 右

    // 当一个左子树为空,右不为空,这时并不是最低点
    if (node->left == NULL && node->right != NULL) { 
        return 1 + rightDepth;
    }
    // 当一个右子树为空,左不为空,这时并不是最低点
    if (node->left != NULL && node->right == NULL) { 
        return 1 + leftDepth;
    }
    // 此时左右子树都为空
    int result = 1 + min(leftDepth, rightDepth); 
    return result;
}

int minDepth(struct TreeNode *root) {
    return getDepth(root);
}

精简代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define min(a, b) ((a) > (b) ? (b) : (a))

int minDepth(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    if (root->left == NULL && root->right != NULL) {
        return 1 + minDepth(root->right);
    }
    if (root->left != NULL && root->right == NULL) {
        return 1 + minDepth(root->left);
    }
    return 1 + min(minDepth(root->left), minDepth(root->right));
}

层序遍历:当左右孩子都为空的时候,说明是最低点的一层了

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define min(a, b) ((a) > (b) ? (b) : (a))

int minDepth(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    int depth = 0;
    struct TreeNode *queue[100001];
    int head = 0;
    int tail = 0;
    queue[++tail] = root; // head:不存放数据,tail:存放数据
    while (head < tail) {
        int last = tail;
        depth++;
        int flag = 0;
        while (head < last) {
            struct TreeNode *node = queue[++head];
            if (node->left) {
                queue[++tail] = node->left;
            }
            if (node->right) {
                queue[++tail] = node->right;
            } 
            if (!node->left && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出
                flag = 1;
                break;
            }
        }
        if (flag == 1) {
            break;
        }
    }
    return depth;
}

16. 完全二叉树的节点个数

先序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

void pre_order(struct TreeNode *root, int *num) {
    if (root == NULL) {
        return;
    }
    (*num)++;
    pre_order(root->left, num);
    pre_order(root->right, num);
}

int countNodes(struct TreeNode *root) {
   int num = 0;
   pre_order(root, &num); 
   return num;
}

中序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

void in_order(struct TreeNode *root, int *num) {
    if (root == NULL) {
        return;
    }
    in_order(root->left, num);
    (*num)++;
    in_order(root->right, num);
}

int countNodes(struct TreeNode *root) {
   int num = 0;
   in_order(root, &num); 
   return num;
}

后序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int post_order(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    int leftNum = post_order(root->left); // 左
    int rightNum = post_order(root->right); // 右
    int treeNum = leftNum + rightNum + 1; // 中
    return treeNum;
}

int countNodes(struct TreeNode *root) {
   return post_order(root);
}

精简代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int post_order(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    return post_order(root->left) + post_order(root->right) + 1;
}

int countNodes(struct TreeNode *root) {
   return post_order(root);
}

层序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int countNodes(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    int num = 0;
    struct TreeNode *queue[50001];
    int head = 0, tail = 0;
    queue[++tail] = root;
    while (head < tail) {
        int last = tail;
        while (head < last) {
            struct TreeNode *p = queue[++head];
            num++;
            if (p->left) {
                queue[++tail] = p->left;
            }
            if (p->right) {
                queue[++tail] = p->right;
            }
        }
    }
    return num;
}

17. 平衡二叉树

  • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数

  • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数

可以使用层序遍历来求深度,但是不能直接用层序遍历来求高度

后序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define max(a, b) ((a) > (b) ? (a) : (b)) 

// 返回以该节点为根节点的二叉树的高度,如果不是二叉搜索树了则返回-1
int getDepth(struct TreeNode *node) {
    if (node == NULL) {
        return 0;
    }
    int leftDepth = getDepth(node->left); // 左
    if (leftDepth == -1) {
        return -1;
    }     
    int rightDepth = getDepth(node->right); // 右
    if (rightDepth == -1) {
        return -1;
    }

    int result;
    if (abs(leftDepth - rightDepth) > 1) {  // 中
        result = -1;
    } else {
        result = 1 + max(leftDepth, rightDepth); // 以当前节点为根节点的最大高度
    }
    return result;
}

bool isBalanced(struct TreeNode *root) {
    return getDepth(root) == -1 ? false : true; 
}

精简代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define max(a, b) ((a) > (b) ? (a) : (b)) 

// 返回以该节点为根节点的二叉树的高度,如果不是二叉搜索树了则返回-1
int getDepth(struct TreeNode *node) {
    if (node == NULL) {
        return 0;
    }
    int leftDepth = getDepth(node->left);
    if (leftDepth == -1) { // 说明左子树已经不是二叉平衡树
        return -1;
    }
    int rightDepth = getDepth(node->right);
    if (rightDepth == -1) { // 说明右子树已经不是二叉平衡树
        return -1;
    }
    return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);
}

bool isBalanced(struct TreeNode *root) {
    return getDepth(root) == -1 ? false : true; 
}

18. 二叉树的所有路径

思路:回溯

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void dfs(struct TreeNode *root, char **res, int *returnSize, int *path, int pathSize) {
    if (root == NULL) {
        return;
    }
    // 当前节点是叶子节点
    if (root->left == NULL && root->right == NULL) {
        char *temp = (char*)malloc(sizeof(char) * 1001);
        int len = 0;
        for (int i = 0; i < pathSize; i++) {
            len += sprintf(temp + len, "%d->", path[i]);
        }
        sprintf(temp + len, "%d", root->val);
        res[(*returnSize)++] = temp; // 把路径加入到答案中
        return;
    }
    path[pathSize++] = root->val; // 当前节点不是叶子节点,继续递归遍历
    dfs(root->left, res, returnSize, path, pathSize);
    dfs(root->right, res, returnSize, path, pathSize);

}

char** binaryTreePaths(struct TreeNode *root, int *returnSize) {
    char **res = (char**)malloc(sizeof(char*) * 1001);
    *returnSize = 0;
    int path[1001];
    dfs(root, res, returnSize, path, 0);
    return res;
}

19. 相同的树

代码实现:先序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool dfs(struct TreeNode *p, struct TreeNode *q) {
    // 都为空
    if (p == NULL && q == NULL) {
        return true;
    }
    // 一个为空,一个不为空
    if ((p && q == NULL) || (p == NULL && q)) {
        return false;
    }
    // 两个都不为空
    if (p->val != q->val) {
        return false;
    }
    return dfs(p->left, q->left) && dfs(p->right, q->right);
}

bool isSameTree(struct TreeNode *p, struct TreeNode *q) {
    return dfs(p, q);
}

20. 左叶子之和

先序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int sumOfLeftLeaves(struct TreeNode *root){
    if (root == NULL) {
        return 0;
    }
    int midValue = 0;
    if (root->left && root->left->left == NULL && root->left->right == NULL) { // 中
        midValue = root->left->val;
    }
    int leftValue = sumOfLeftLeaves(root->left); // 左
    int rightValue = sumOfLeftLeaves(root->right); // 右
    int sum = midValue + leftValue + rightValue;
    return sum;
}

精简代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int sumOfLeftLeaves(struct TreeNode *root){
    if (root == NULL) {
        return 0;
    }
    int midValue = 0;
    if (root->left && root->left->left == NULL && root->left->right == NULL) { // 中
        midValue = root->left->val;
    }
    int sum = midValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    return sum;
}

21. 找树左下角的值

层序遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int findBottomLeftValue(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    struct TreeNode *queue[10001];
    int head = 0, tail = 0;
    queue[++tail] = root;
    int num;
    while (head < tail) {
        int last = tail;
        int flag = 1;
        while (head < last) {
            struct TreeNode *p = queue[++head];
            if (flag) {
                num = p->val;
                flag = 0;
            }
            if (p->left) {
                queue[++tail] = p->left;
            }
            if (p->right) {
                queue[++tail] = p->right;
            }
        }
    }
    return num;
}

先序遍历:深度最大的叶子节点一定是最后一行,记录深度最大的叶子节点,此时就是树的最后一行最左边的值

int maxLen;
int maxleftValue;
void dfs(struct TreeNode *root, int leftLen) {
    if (root->left == NULL && root->right == NULL) {
        if (leftLen > maxLen) {
            maxLen = leftLen;
            maxleftValue = root->val;
        }
        return;
    }
    if (root->left) {
        leftLen++;
        dfs(root->left, leftLen);
        leftLen--; // 回溯
    }
    if (root->right) {
        leftLen++;
        dfs(root->right, leftLen);
        leftLen--; // 回溯 
    }
}
int findBottomLeftValue(struct TreeNode *root) {
    maxLen = INT32_MIN;
    dfs(root, 0);
    return maxleftValue;
}

22. 路径总和

先序遍历:dfs

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool dfs(struct TreeNode *root, int targetSum, int sum) {
    if (root == NULL) {
        return false;
    }
    // 叶子节点
    if (root->left == NULL && root->right == NULL) {
        sum += root->val;
        if (sum == targetSum) {
            return true;
        }
        return false;
    }
    sum += root->val;
    bool l = dfs(root->left, targetSum, sum);
    if (l == true) {
        return true;
    }
    bool r = dfs(root->right, targetSum, sum);
    if (r == true) {
        return true;
    }
    return l || r;
}

bool hasPathSum(struct TreeNode *root, int targetSum) {
    return dfs(root, targetSum, 0);
}

23. 路径总和 ||

先序遍历:回溯

/**
 * 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().
 */

int **res;
int resSize;
int *path;
int pathSize;

void dfs(struct TreeNode *root, int targetSum, int **returnColumnSizes) {
    if (root == NULL) {
        return;
    }
    path[pathSize++] = root->val;
    targetSum -= root->val;
    if (root->left == NULL && root->right == NULL && targetSum == 0) {
        int *ret = malloc(sizeof(int) * pathSize);
        memcpy(ret, path, sizeof(int) *pathSize);
        res[resSize] = ret;
        (*returnColumnSizes)[resSize++] = pathSize;
    }
    dfs(root->left, targetSum, returnColumnSizes);
    dfs(root->right, targetSum, returnColumnSizes);
    pathSize--;
}

int** pathSum(struct TreeNode *root, int targetSum, int *returnSize, int **returnColumnSizes) {
    res = malloc(sizeof(int*) * 5000);
    resSize = 0;
    path = malloc(sizeof(int) * 5000);
    pathSize = 0;
    *returnColumnSizes = malloc(sizeof(int) * 5000);
    dfs(root, targetSum, returnColumnSizes);
    *returnSize = resSize;
    return res;
}

24. 😭从中序与后序遍历序列构造二叉树

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中                序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

代码实现:
 

25. 😭从前序与中序遍历序列构造二叉树

26. 最大二叉树

分析:构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* construct(const int *nums, int l, int r) {
    if (l > r) {
        return NULL;
    }
    int best = l; // 最大值下标
    for (int i = l + 1; i <= r; i++) {
        if (nums[i] > nums[best]) {
            best = i;
        }
    }
    struct TreeNode *node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    node->val = nums[best];
    node->left = construct(nums, l, best - 1);
    node->right = construct(nums, best + 1, r);
    return node;
}

struct TreeNode* constructMaximumBinaryTree(int *nums, int numsSize) {
    return construct(nums, 0, numsSize - 1);
}

27. 合并两个二叉树

代码实现:递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* mergeTrees(struct TreeNode *root1, struct TreeNode *root2) {
    if (root1 == NULL) {
        return root2;
    }
    if (root2 == NULL) {
        return root1;
    }
    struct TreeNode *node = malloc(sizeof(*node));
    int val = 0;
    if (root1) {
        val += root1->val;
    }
    if (root2) {
        val += root2->val;
    }
    node->val = val;
    node->left = mergeTrees(root1->left, root2->left);
    node->right = mergeTrees(root1->right, root2->right);
    return node;
}

28. 二叉搜索树中的搜索

迭代:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* searchBST(struct TreeNode *root, int val) {
    if (root == NULL) {
        return NULL;
    }
    struct TreeNode *p = root;
    while (p) {
        if (p->val == val) {
            return p;
        }
        if (p->val > val) {
            p = p->left;
        } else {
            p = p->right;
        }
    }
    return NULL;
}

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* searchBST(struct TreeNode *root, int val) {
    if (root == NULL) {
        return NULL;
    }
    if (root->val == val) {
        return root;
    }
    struct TreeNode *l = searchBST(root->left, val);
    if (l != NULL) {
        return l;
    }
    struct TreeNode *r = searchBST(root->right, val);
    if (r != NULL) {
        return r;
    }
    return l || r;
}

29. 验证二叉搜索树

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode *pre;
bool isValidBSTHelper(struct TreeNode *root) {
    if (root == NULL) {
        return true;
    }
    // 检查左子树
    bool left = isValidBSTHelper(root->left);
    // 检查当前节点
    if (pre != NULL && pre->val >= root->val) {
        return false;
    }
    // 记录前一个节点
    pre = root;
    // 检查右子树
    bool right = isValidBSTHelper(root->right);
    return left && right;
}

bool isValidBST(struct TreeNode* root) {
    pre = NULL;
    return isValidBSTHelper(root);
}

30. 二叉搜索树的最小绝对差

中序遍历 —— 把二叉搜索树转换成有序数组,然后遍历一遍数组

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int path[10000];
int pathSize;

void mid_order(struct TreeNode *root) {
    if (root == NULL) {
        return;
    }
    mid_order(root->left);
    path[pathSize++] = root->val;
    mid_order(root->right);
}

int getMinimumDifference(struct TreeNode *root) {
    pathSize = 0;
    mid_order(root);
    int min = path[1] - path[0];
    for (int i = 2; i < pathSize; i++) {
        int num = path[i] - path[i - 1];
        if (num < min) {
            min = num;
        }
    }
    return min;
}

在二叉搜索树中序遍历的过程中,可以直接计算,用一个pre节点记录一下cur节点的前一个节点

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
#define min(a, b) ((a) > (b) ? (b) : (a))
int result;
struct TreeNode *pre;

void mid_order(struct TreeNode *cur) {
    if (cur == NULL) {
        return;
    }
    mid_order(cur->left); // 左
    if (pre != NULL) { // 中
        result = min(result, cur->val - pre->val);
    }
    pre = cur; // 记录前一个
    mid_order(cur->right);  // 右
}

int getMinimumDifference(struct TreeNode *root) {
    result = INT32_MAX;
    pre = NULL;
    mid_order(root);
    return result;
}

31. 二叉搜索树中的众数

32. 二叉树的最近公共祖先

代码实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* lowestCommonAncestor(struct TreeNode *root, struct TreeNode *p, struct TreeNode *q) {
    if (root == q || root == p || root == NULL) {
        return root;
    }
    struct TreeNode *l = lowestCommonAncestor(root->left, p, q);
    struct TreeNode *r = lowestCommonAncestor(root->right, p, q);
    if (l != NULL && r != NULL) {
        return root;
    }
    if (l == NULL && r != NULL) {
        return r;
    } else if (l != NULL && r == NULL) {
        return l;
    } else {
        return NULL;
    }
}

33. 搜索树的公共祖先问题

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* dfs(struct TreeNode *root, struct TreeNode *p, struct TreeNode *q) {
    if (root == NULL) {
        return NULL;
    }
    if (root->val > p->val && root->val > q->val) { // 左
        struct TreeNode *l = dfs(root->left, p, q);
        if (l != NULL) {
            return l;
        }
    }

    if (root->val < p->val && root->val < q->val) {   // 右
        struct TreeNode *r = dfs(root->right, p, q);
        if (r != NULL) {
            return r;
        }
    }
    return root;
}

struct TreeNode* lowestCommonAncestor(struct TreeNode *root, struct TreeNode *p, struct TreeNode *q) {
    return dfs(root, p, q);
}

迭代:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* lowestCommonAncestor(struct TreeNode *root, struct TreeNode *p, struct TreeNode *q) {
    while (root) {
        if (root->val > p->val && root->val > q->val) {
            root = root->left;
        } else if (root->val < p->val && root->val < q->val) {
            root = root->right;
        } else {
            return root;
        }
    }
    return NULL;
}

34. 二叉搜索树中的插入操作

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* insertIntoBST(struct TreeNode *root, int val) {
    if (root == NULL) {
        struct TreeNode *node = malloc(sizeof(*node));
        node->left = node->right = NULL;
        node->val = val;
        return node;
    }
    if (root->val > val) {
        root->left = insertIntoBST(root->left, val);
    }
    if (root->val < val) {
        root->right = insertIntoBST(root->right, val);
    }
    return root;
}

迭代:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* insertIntoBST(struct TreeNode *root, int val) {
    // 创建一个节点
    struct TreeNode *node = malloc(sizeof(*node));
    node->left = node->right = NULL;
    node->val = val;

    struct TreeNode *p = root;
    struct TreeNode *pf = NULL;
    while (p) {
        if (p->val > val) {
            pf = p;
            p = p->left;
        } else {
            pf = p;
            p = p->right;
        }
    }
    if (pf == NULL) {
        return node;
    }
    if (pf->val > val) {
        pf->left = node;
    } else {
        pf->right = node;
    }
    return root;
}

35. 删除二叉搜索树中的节点

分析:

有以下五种情况:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了

  • 找到删除的节点

    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点

    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点

    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点

    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左边节点的左孩子上,返回删除节点右孩子为新的根节点

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* deleteNode(struct TreeNode *root, int key) {
    // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
    if (root == NULL) {
        return root;
    }
    if (root->val == key) {
        // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
        // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
        if (root->left == NULL) {
            return root->right;
        // 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
        } else if (root->right == NULL) {
            return root->left;
        // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左边节点的左孩子的位置
        // 并返回删除节点右孩子为新的根节点
        } else {
            struct TreeNode *node = root->right; // 找右子树最左边的节点
            while (node->left != NULL) {
                node = node->left;
            }
            node->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
            return root->right; // 返回旧root的右孩子作为新root
        }
    }
    if (root->val > key) {
        root->left = deleteNode(root->left, key);
    }
    if (root->val < key) {
        root->right = deleteNode(root->right, key);
    }
    return root;
}

迭代:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* deleteNode(struct TreeNode *root, int key) {
    if (root == NULL) {
        return root;
    }
    // 1. 找到值为x的节点 遍历
    struct TreeNode *p = root;
    struct TreeNode *pf = NULL;
    while (p) {
        if (p->val == key) {
            break;
        } else if (p->val > key) {
            pf = p;
            p = p->left;
        } else {
            pf = p;
            p = p->right;
        }
    }
    // 2. 没有找到 return root
    if (p == NULL) {
        return root;
    }
    // 3.找到了 就去删除 分情况删除
    /*
		1).p没有子树 p就是叶子结点
			p为根节点
			p是父节点左孩子
			p是父节点右孩子
		2).p有两个子树
		3).p有一个子树
	*/
    if (!p->left && !p->right) { // p没有子树,p就是叶子节点
        if (p == root) { // p为根节点
            free(p);
            return NULL;
        } else { // p不是根节点
            if (pf->left == p) { // p为父节点左孩子
                pf->left = NULL;
                free(p);
            } else if (pf->right == p) { // p为父节点右孩子
                pf->right = NULL;
                free(p);
            }
        }
    } else if (p->left && p->right) { // p有两个子树
        // 找p右子树中最小的节点
        struct TreeNode *p2 = p->right;
        while (p2->left) {
            p2 = p2->left;
        }
        p2->left = p->left;
        if (pf == NULL) { // p是根节点
            root = p->right;
            p->right = NULL;
            free(p);
        } else if (pf->left == p) {
            pf->left = p->right;
            p->left = p->right = NULL;
            free(p);
        } else {
            pf->right = p->right;
            p->left = p->right = NULL;
            free(p);
        }
    } else { // 只有一个子树
        if (p == root) { // p是根节点
            if (p->left) { // 只存在左孩子
                root = p->left;
                p->left = NULL;
                free(p);
            } else { // 只存在右孩子
                root = p->right;
                p->right = NULL;
                free(p);
            }
        } else if (pf->left == p) { // p不是根结点,p是pf的左子
            if (p->right) { // p只存在右孩子
                pf->left = p->right; // p的右孩子成为pf的左孩子
                p->right = NULL;
                free(p);
            } else { // p只存在左孩子
                pf->left = p->left; // p的左孩子成为pf的左孩子
                p->left = NULL;
                free(p);
            }
        } else if (pf->right == p) { // p不是根结点,p是pf的右子
            if (p->left) { // p只存在右孩子
                pf->right = p->left; // p的右孩子成为pf的右孩子
                p->left = NULL;
                free(p);
            } else { // p只存在左孩子
                pf->right = p->right; // p的右孩子成为pf的右孩子
                p->right = NULL;
                free(p);
            }
        }
    }
    return root;
}

36. 修剪二叉搜索树

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* trimBST(struct TreeNode *root, int low, int high) {
    if (root == NULL) {
        return NULL;
    }
    if (root->val < low) {
        // 寻找符合区间[low, high]的节点
        return trimBST(root->right, low, high);
    }
    if (root->val > high) {
        // 寻找符合区间[low, high]的节点
        return trimBST(root->left, low, high);
    }
    // root->left接入符合条件的左孩子
    root->left = trimBST(root->left, low, high);
    // root->right接入符合条件的右孩子
    root->right = trimBST(root->right, low, high);
    return root;
}

37. 将有序数组转换为二叉搜索树

分析:分割数组中间位置的节点

递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

// 左闭右闭
struct TreeNode* pre_order(int *nums, int l, int r) {
    if (l > r) {
        return NULL;
    }
    int mid = (r + l) / 2;
    struct TreeNode *root = malloc(sizeof(*root));
    root->val = nums[mid];
    root->left = pre_order(nums, l, mid - 1);
    root->right = pre_order(nums, mid + 1, r);
    return root;
}

struct TreeNode* sortedArrayToBST(int *nums, int numsSize) {
    return pre_order(nums, 0, numsSize - 1);
}

38. ✌从二叉搜索树到更大和树

反中序遍历(递归):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int pre; // 记录前一个结点的数值

// 反中序遍历(右左中)
void mid_order(struct TreeNode *root) {
    if (root == NULL) {
        return;
    }
    mid_order(root->right);
    root->val += pre;
    pre = root->val;
    mid_order(root->left);
}

struct TreeNode* bstToGst(struct TreeNode *root) {
    pre = 0;
    mid_order(root);
    return root;
}

反中序遍历(迭代):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define MAX_NODE 100

int pre; // 记录前一个结点的数值

// 反中序遍历(右左中) 迭代
void mid_order(struct TreeNode *root) {
    if (root == NULL) {
        return;
    }
    struct TreeNode *stack[MAX_NODE]; // 创建一个栈
    int top = -1; // 栈顶
    struct TreeNode *p = root;
    struct TreeNode *q = NULL;
    while (p || top != -1) {
		if (p) {
			stack[++top] = p;
			p = p->right; // 右
		} else {
			q = stack[top];
			q->val += pre;
            pre = q->val;
            top--;
			p = q->left; // 左
		}
	}
}

struct TreeNode* bstToGst(struct TreeNode *root) {
    pre = 0;
    mid_order(root);
    return root;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值