代码随想录算法训练营Day23 | 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树

669. 修剪二叉搜索树

这题需要发现一个点:如果一个节点不满足区间条件,那么其某一边的子树一定也不满足区间条件(如一个节点的值大于上界,那么它右子树的所有节点也一定都大于上界),所以这题只会出现450中的情况1、2、3,不会出现最棘手的情况4。

包含内存释放操作的递归写法(内存释放需要多写很多行代码):

// 后序遍历,从底向上释放该树所有节点的内存
void deleteTree(TreeNode* cur) {
	if (!cur)
		return;
	deleteTree(cur->left);
	deleteTree(cur->right);
	cur = nullptr;		// 注意指针置空后再delete
	delete cur;
}

// 注意:一个节点被删除,那么其某一边的子树一定被一起删除
TreeNode* trimNode(TreeNode* cur, int& low, int& high) {
	if (!cur)
		return nullptr;

	// 如果低于下界,该节点连带左子树都应该被删除,递归并返回右子树
	if (cur->val < low) {
		// 递归右子树,将更新后的右子树保存在一个临时量中
		cur->right = trimNode(cur->right, low, high);
		TreeNode* temp = cur->right;
		// 删除所有左子树节点的内存
		deleteTree(cur->left);
		// 删除当前节点的内存
		cur = nullptr;
		delete cur;
		// 返回右子树
		return temp;
	}
	// 如果高于上界,该节点连带右子树都应该被删除,递归并返回左子树
	else if (cur->val > high) {
		cur->left = trimNode(cur->left, low, high);
		TreeNode* temp = cur->left;
		deleteTree(cur->right);
		cur = nullptr;
		delete cur;
		return temp;
	}
	// 如果处于范围内,递归更新左右子树,返回节点自身
	else {
		cur->left = trimNode(cur->left, low, high);
		cur->right = trimNode(cur->right, low, high);
		return cur;
	}
}

TreeNode* trimBST(TreeNode* root, int low, int high) {
	return trimNode(root, low, high);
}

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

这题比较简单,由于数组已经排序,每次选序列中间的节点为根节点,不断分割左右子树即可(选中间节点是为了保证左右平衡)

// 前序遍历,不断取序列居中值构造节点
TreeNode* traversal(int left, int right, vector& nums) {
	if (right - left == 0)
		return nullptr;
    // 中
	int middle = (left + right) / 2;
	TreeNode* root = new TreeNode(nums[middle]);
    // 左
	root->left = traversal(left, middle, nums);
    // 右
	root->right = traversal(middle + 1, right, nums);
	return root;
}

TreeNode* sortedArrayToBST(vector& nums) {
	return traversal(0, nums.size(), nums);
}

538. 把二叉搜索树转换为累加树

这题需要从二叉搜索树中的最大值开始累加,而二叉搜索树中序遍历是单调递增的,所以只要以反转的中序(即右-中-左)顺序来遍历累加即可,累加操作比较常规。 

一个节点需要累加的值等于遍历过程中上一个节点完成累加后的值(简单的数学推理),所以使用双指针法记录上一个节点的值:

void traversal(TreeNode* cur, int& pre) {
	if (!cur)
		return;
	// 右
	traversal(cur->right, pre);
	// 中
	cur->val += pre;
	pre = cur->val;
	// 左
	traversal(cur->left, pre);
}

// 以右-中-左顺序遍历(反转的中序遍历),不断累加
TreeNode* convertBST(TreeNode* root) {
	int pre = 0;
	traversal(root, pre);
	return root;
}

二叉树总结

(二叉树章节完结撒花!!!)

等周末有空了再来更新(懒)

你可能感兴趣的:(算法)