DFS 回溯 剪枝 合集

46.全排列

在这里插入图片描述

#python
class Solution:
    #def permute(self, nums: List[int]) -> List[List[int]]:
    def permute(self, nums):
        res = []
        def dfs(newNnums, res1):
            if(newNnums == []):
                res.append(res1)              
                return 

            for i in range(len(newNnums)):                                 
                dfs(newNnums[:i]+newNnums[i+1:], res1+[newNnums[i]])
                #此处用res1+[newNnums[i]],只是在传参的时候传入变化后的列表,但是res1本身并没有发生变化

        dfs(nums, [])
        return res
#python  这个版本不能得到正确答案    
#这是自己本来的思路  先append,再pop,但是这样会改变res1的值,导致res跟着改变

class Solution:
    #def permute(self, nums: List[int]) -> List[List[int]]:
    def permute(self, nums):
        res = []
        def dfs(newNnums, res1):
            if(newNnums == []):
                res.append(res1)              
                return 

            for i in range(len(newNnums)):                                 
                res1.append(newNnums[i])
                dfs(newNnums[:i]+newNnums[i+1:], res1)
                res1.pop()

        dfs(nums, [])
        return res
#这个是上面版本的修正版本  但这个又要append,又要pop,比较耗时
class Solution:
    #def permute(self, nums: List[int]) -> List[List[int]]:
    def permute(self, nums):
        res = []
        def dfs(newNnums, res1):
            if(newNnums == []):
                res.append(res1[:])              
                return 

            for i in range(len(newNnums)):                                 
                res1.append(newNnums[i])
                dfs(newNnums[:i]+newNnums[i+1:], res1)
                res1.pop()

        dfs(nums, [])
        return res

47.全排列 II

在这里插入图片描述

#python   anan写的 顺利通过
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        res = []
        def dfs(nums, res1):
            if(nums == []):
                res.append(res1[:])              
                return 
            for i in range(len(nums)): 
                print(i, nums[i], nums[0:i], nums)                   
                if(i > 0 and nums[i] in nums[0:i]):  #加了一个判断条件,如果之前判断过,此处就不用再考虑                  
                    continue                   
                res1.append(nums[i])
                dfs(nums[:i]+nums[i+1:], res1)
                res1.pop()

        dfs(nums, [])
        return res

78.子集

在这里插入图片描述

#python  anan写的  ide可以运行出来 但leetcode会超时
class Solution:
    def subsets(self, nums):
        res = []

        def helper(nums):
            if(nums not in res):
                res.append(nums)

            if(nums == []):
                #print(res)
                return 

            for i in range(len(nums)):
                helper(nums[:i] + nums[i+1:])

        helper(nums)
        return res

#[[1, 2, 3], [2, 3], [3], [], [2], [1, 3], [1], [1, 2]]
#python   anan写的  通过了

class Solution:
    def subsets(self, nums):
        res = []

        def helper(nums, tmp):
            if(tmp not in res):
                res.append(tmp[:])

            for i in range(len(nums)):
                tmp.append(nums[i])
                helper(nums[i+1:], tmp)
                tmp.pop()

        helper(nums, [])
        return res
 #[1,2,3]        [[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]

90.子集 II

在这里插入图片描述

#python
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        res = []

        def helper(nums, tmp):
            if(tmp not in res):
                res.append(tmp[:])

            for i in range(len(nums)):
                tmp.append(nums[i])
                helper(nums[i+1:], tmp)
                tmp.pop()

        helper(sorted(nums), [])    对给定数组进行排序
        return res
 #[1,2,2]    [[],[1],[1,2],[1,2,2],[2],[2,2]]
 #[4,4,4,1,4]      [[],[1],[1,4],[1,4,4],[1,4,4,4],[1,4,4,4,4],[4],[4,4],[4,4,4],[4,4,4,4]]

39.组合总和

在这里插入图片描述
在这里插入图片描述

#python   anan写的  通过啦  啦啦啦

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res = []

        def helper(candidates, target, tmp):
            if(target == 0):
                res.append(tmp[:])

            for i in range(len(candidates)):
                tmp.append(candidates[i])
                if(target-candidates[i] >= 0):
                    helper(candidates[i:], target-candidates[i], tmp)
                tmp.pop()

        helper(candidates, target, [])
        return res

40.组合总和 II

在这里插入图片描述
在这里插入图片描述

#python
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        res = []

        def helper(candidates, target, tmp):
            if(target == 0):
                res.append(tmp[:])

            for i in range(len(candidates)):
                tmp.append(candidates[i])
                if(target-candidates[i] >= 0 and candidates[i] not in candidates[:i]):  #此处加了一个判断条件
                    helper(candidates[i+1:], target-candidates[i], tmp)
                tmp.pop()

        helper(sorted(candidates), target, [])   #此处对输入数组进行了排序
        return res

77.组合

在这里插入图片描述

#python ana写的
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []

        def helper(nums, tmp):
            if(len(tmp) == k):
                res.append(tmp[:])
                return
            
            i = 0
            while(nums and i < len(nums)):                
                tmp.append(nums[i])
                #print(tmp)
                helper(nums[i+1:],tmp)
                tmp.pop()
                i+=1

        nums = [i+1 for i in range(n)]        
        helper(nums, [])
        return res
# [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
#python  anan写的
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []

        def helper(nums, tmp):
            if(len(tmp) == k):
                res.append(tmp[:])
                return
            
            for i in range(len(nums)):            
                tmp.append(nums[i])
                #print(tmp)
                helper(nums[i+1:],tmp)
                tmp.pop()
                i+=1

        nums = [i+1 for i in range(n)]        
        helper(nums, [])
        return res

543.二叉树的直径

在这里插入图片描述

DFS 全局变量

在这里插入图片描述

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

int helper(struct TreeNode * root){   //该结点作为根节点的高度
    int leftHeight;
    int rightHeight;

    if(root){
        //处理左子树
        leftHeight = helper(root->left);
        //处理右子树
        rightHeight = helper(root->right);
        //操作本结点
        result = leftHeight+rightHeight > result ? leftHeight+rightHeight : result;
        return leftHeight>rightHeight ? leftHeight+1 : rightHeight+1;
    }else{
        return 0;
    }   
}

int diameterOfBinaryTree(struct TreeNode* root){
    result = 0;   //刚开始直接在定义全局变量时初始化,老是出错,改在这儿初始化就没有问题了
    helper(root);
    return root ? result : 0;
}
//java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int result = 0;
    public int diameterOfBinaryTree(TreeNode root) {
        helper(root);
        return result;
    }

    public int helper(TreeNode root){
        int leftHeight;
        int rightHeight;

        if(root != null){
            leftHeight = helper(root.left);
            rightHeight = helper(root.right);
            result = Math.max(leftHeight+rightHeight, result); 
            return Math.max(leftHeight, rightHeight)+1;
        }else{
            return 0;
        }   
    }
}
#python
class Solution(object):
    def diameterOfBinaryTree(self, root):
        self.ans = 1
        def depth(node):
            # 访问到空节点了,返回0
            if not node: return 0
            # 左儿子为根的子树的深度
            L = depth(node.left)
            # 右儿子为根的子树的深度
            R = depth(node.right)
            # 计算d_node即L+R+1 并更新ans
            self.ans = max(self.ans, L+R+1)
            # 返回该节点为根的子树的深度
            return max(L, R) + 1

        depth(root)
        return self.ans - 1

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree/solution/er-cha-shu-de-zhi-jing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

DFS python 不用全局变量

#python
# 返回二元 tuple (depth, diameter)
# depth 表示子树的最大深度,diameter 表示子树的最长路径(直径)
def traverse(root):
    if root is None:
        return (0, 0)

    left_depth, left_diam = traverse(root.left)
    right_depth, right_diam = traverse(root.right)
    # 求二叉树深度的常规方法
    depth = 1 + max(left_depth, right_depth)
    # 套用上面推导出的最长路径公式
    diam = max(left_diam, right_diam, left_depth + right_depth)
    return depth, diam

def diameterOfBinaryTree(root):
    depth, diam = traverse(root)
    return diam

作者:nettee
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree/solution/liang-chong-si-lu-shi-yong-quan-ju-bian-liang-yu-b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

562.二叉树的坡度

在这里插入图片描述

DFS 全局变量

//java  anan 官方的和此类似
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int tilt;

    public int findTilt(TreeNode root) {
        tilt = 0;
        dfs(root);
        return tilt;
    }

    public int dfs(TreeNode root){
        if(root != null){
            int left = dfs(root.left);
            int right = dfs(root.right);
            tilt += Math.abs(left-right);
            return left+right+root.val;
        }else{
            return 0;
        }
    }
}

110.平衡二叉树

在这里插入图片描述
在这里插入图片描述

DFS全局变量

本题与其他题的区别之处:之前的题都是定义一个全局变量,每个递归都会更改这个全局变量的值,最后返回这个值即可;但是本题属于判断题型,如果定义全局变量,只要这个变量为false,就必须返回false,所以只有在满足某些条件下才需要修改这个全局变量的值。见下:

//java   anan
class Solution {
    boolean balance;

    public boolean isBalanced(TreeNode root) {  
        balance = true;     
        height(root);
        return balance;
    }

    public int height(TreeNode root){
        if(root == null)  return 0;
        int leftHeight = height(root.left);
        int rightHeight = height(root.right);

        if( Math.abs(leftHeight-rightHeight) > 1)   balance = false;
        return Math.max(leftHeight, rightHeight) + 1;
    }

}

DFS 不用全局变量

//java  参考别人的
//每次不平衡时返回一个标志,直到最后
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public boolean isBalanced(TreeNode root) {       
        return height(root) != -1;
    }

    public int height(TreeNode root){
        if(root == null)  return 0;
        int leftHeight = height(root.left);
        int rightHeight = height(root.right);
        if(leftHeight >= 0 && rightHeight >= 0 && Math.abs(leftHeight-rightHeight) <= 1){
            return Math.max(leftHeight, rightHeight) + 1;
        }else{
            return -1;   //-1作为不平衡的标志
        }
    }
}

687.最长同值路径

在这里插入图片描述
在这里插入图片描述

//java  anan 2020.3.10
class Solution {
    int res;

    public int dfs(TreeNode root){
        if(root != null){
            int tmp = 0;   //返回的值  左右子树中等值路径的最大数
            int tmp1 = 0;  //比较的数 该节点同值的最长路径
            int l = dfs(root.left);
            int r= dfs(root.right);


            //System.out.print("val=" +  root.val + " " + l + " " + r);

            if(root.left != null && root.right != null){
                if(root.val == root.left.val && root.val == root.right.val){
                    tmp = Math.max(l,r)+1;  tmp1 = l+r+2;
                }else if(root.val == root.left.val){
                    tmp = l+1;     tmp1 = l+1;
                } 
                else if(root.val == root.right.val){
                    tmp = r+1;    tmp1 = r+1;
                } 
            }else if(root.left != null){
                if(root.val == root.left.val){
                    tmp = l+1;     tmp1 = l+1;
                } 
            }else if(root.right != null){
                if(root.val == root.right.val){
                    tmp = r+1;    tmp1 = r+1;
                } 
            }

            //System.out.print("**" + tmp + res + " ");
            res = Math.max(res, tmp1);
            //System.out.println("**final:" + res + " ");

            return tmp;
        }else{
            return 0;
        }
    }

    public int longestUnivaluePath(TreeNode root) {
        res = 0;
        dfs(root);
        return res;
    }
}
//java
//官解和自己的解法相似,只是自己在处理结点时有点过于繁琐,而官解的这个很简洁,值得学习
class Solution {
    int ans;
    public int longestUnivaluePath(TreeNode root) {
        ans = 0;
        arrowLength(root);
        return ans;
    }
    public int arrowLength(TreeNode node) {
        if (node == null) return 0;
        int left = arrowLength(node.left);
        int right = arrowLength(node.right);
        int arrowLeft = 0, arrowRight = 0;
        if (node.left != null && node.left.val == node.val) {
            arrowLeft += left + 1;
        }
        if (node.right != null && node.right.val == node.val) {
            arrowRight += right + 1;
        }
        ans = Math.max(ans, arrowLeft + arrowRight);
        return Math.max(arrowLeft, arrowRight);
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-univalue-path/solution/zui-chang-tong-zhi-lu-jing-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

129.求根到叶子结点数字之和

在这里插入图片描述
在这里插入图片描述

DFS递归 使用全局变量

问题:python全局变量该怎么用?

#python anan 2020.3.10
class Solution:
    def sumNumbers(self, root: TreeNode) -> int:
        if not root:
            return 0

        res = []
        def dfs(root, tmp):  #tmp当一个字符串  
            if(not root.left and  not root.right):  #叶子结点  左右子树都为空
                tmp = tmp+str(root.val)
                res.append(int(tmp))
                return 
            
            if(root.left):
                dfs(root.left, tmp+str(root.val))
            if(root.right):
                dfs(root.right, tmp+str(root.val))  
                                             
        dfs(root, "")
        print(res)
        return sum(res)
//java  anan
//将每个结点处的值作为字符串,每次遍历一个结点,进行字符串的拼接,到叶子结点后,将这个字符串转化为整型,叠加到全局遍历sum中。
class Solution {
    int sum = 0;

    public void dfs(TreeNode root, String tmp){
        if(root.left==null && root.right==null){
            tmp = tmp+Integer.toString(root.val);
            sum += Integer.parseInt(tmp.toString());
            return ;
        }
        if(root.left != null)  dfs(root.left, tmp+Integer.toString(root.val));
        if(root.right !=  null)  dfs(root.right, tmp+Integer.toString(root.val));
    }

    public int sumNumbers(TreeNode root) {
        if(root==null)   return 0;
        dfs(root, new String(""));
        return sum;
    }
}

DFS 不用全局变量,通过变量回传

//java 别人的  这段代码太漂亮了
class Solution {
    public int sumNumbers(TreeNode root) {
        return helper(root, 0);
    }

    public int helper(TreeNode root, int i){
        if(root == null)  return 0;
        int temp = i*10+root.val;
        if(root.left == null && root.right == null)
            return temp;
        return helper(root.left, temp) + helper(root.right, temp);

    }
}
// 作者:liuzhaoce
// 链接:https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/solution/0-ms-jiao-ke-shu-ji-jie-da-by-liuzhaoce/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安安csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值