代码随想录第二十七天(669、108、538、回溯算法介绍)

669. 修剪二叉搜索树

不能简单地通过递归实现代码,比如:

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr || root->val < low || root->val > high) return nullptr;
        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);
        return root;
    }
};

举例:
代码随想录第二十七天(669、108、538、回溯算法介绍)_第1张图片
在遍历到0这个结点时,因为0满足递归的第一个条件,所以会直接将0的所有子树删除,但是0的右子树的节点满足[1,3]这个范围.

其实就是要考虑0节点右子树

class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root==null) return null;
        if(root.val<low){
            return trimBST(root.right,low,high);
        }
        if(root.val>high){
            return trimBST(root.left,low,high);
        }
        root.left=trimBST(root.left,low,high);
        root.right=trimBST(root.right,low,high);
        return root;
    }
}

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

这道题强调平衡,是怕给出了一个升序的数组后,建立的二叉树是这样的:
代码随想录第二十七天(669、108、538、回溯算法介绍)_第2张图片
如果默认从数组的中间位置开始构建,以中间的节点作为根节点,然后递归的构建左子树和右子树,这个二叉树自然就是平衡的

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        if(nums.length==0) return null;
        return buildTree(nums,0,nums.length-1);
    }
    public TreeNode buildTree(int[] nums,int low,int high){
        if(low>high) return null;
        int mid=(low+high)/2;
        TreeNode root=new TreeNode(nums[mid]);
        root.left=buildTree(nums,low,mid-1);
        root.right=buildTree(nums,mid+1,high);
        return root;
    }
}

注意:
在Java中,由运算结果,由被运算数的最高数据类型决定(float比int类型高)

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

题中给出的例子:
代码随想录第二十七天(669、108、538、回溯算法介绍)_第3张图片
根据答案:就是二叉搜索树遍历的顺序是[0,1,2,3,4,5,6,7,8],而累加树遍历的顺序是相反的,从8开始。所以在二叉搜索树上就是按照右中左的遍历顺序

哈哈,看完答案的思路之后自己写的代码,竟然是对的,比答案还简单,真开心!

class Solution {
    int val=0;//用于存储当前便利的结点之和
    public TreeNode convertBST(TreeNode root) {
        if(root==null) return null;
        root.right=convertBST(root.right);
        root.val+=val;
        val=root.val;
        root.left=convertBST(root.left);
        return root;
    }
}

回溯算法

1、回溯函数也就是递归函数,指的都是一个函数。
2、回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,回溯法并不是什么高效的算法。
3、主要解决的问题种类:
组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等
4、关于组合和排列:
组合是不强调元素顺序的,排列是强调元素顺序
5、模板
习惯是函数起名字为backtracking
回溯算法中函数返回值一般为void

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

你可能感兴趣的:(leetcode,算法,leetcode,数据结构)