剑指offer--树&图 BFS+DFS+回溯

DFS&BFS

刷题路线

004-重建二叉树
017-树的子结构
018-二叉树的镜像
022-从上往下打印二叉树
023-二叉搜索树的后序遍历序列
024-二叉树中和为某一值的路径
026-二叉搜索树与双向链表
038-二叉树的深度
039-平衡二叉树
057-二叉树的下一个结点
058-对称的二叉树
059-按之字形顺序打印二叉树
060-把二叉树打印成多行
061-序列化二叉树
062-二叉搜索树的第k个结点

匹配类二叉树

题目解法题解
重建二叉树递归;迭代两种
树的子结构双重递归;非递归;官方(DFS/DFS+/树哈希)官方递归非递归
二叉树的镜像递归;辅助栈两种
从上往下打印二叉树BFSbfs
按之字形顺序打印二叉树层序遍历+双端队列
把二叉树打印成多行BFS
二叉搜索树的后序遍历序列递归分治;单调栈两种
二叉树中和为某一值的路径回溯回溯
二叉搜索树与双向链表递归(中序遍历)中序遍历
二叉树的深度HashMap;双指针;递归前两种双指针+尾插法
平衡二叉树递归(自顶向下;自底向上)两种
二叉树的下一个节点HashMap;双指针;递归前两种双指针+尾插法
对称的二叉树递归;迭代两种
序列化二叉树DFS先序遍历题解
二叉搜索树的第K个节点迭代;递归(中序遍历+倒序)
矩阵中的路径回溯题解
机器人的运动范围回溯BFS/DFS两种

重建二叉树||从前序与中序遍历序列构造二叉树

解法时间复杂度空间复杂度
递归O(n)O(n)
迭代O(n)O(n)
//递归法
public class Solution {
    //优化(空间换时间):存放in数组数值和下标对应关系;便于快速定位in中根节点位置
    HashMap<Integer,Integer> map=new HashMap<>();
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre==null&&in==null) return null;
        int preLen=pre.length;
        int inLen=in.length;
        if(preLen!=inLen) return new RuntimeException("错误");
        for(int i=0;i<inLen;i++){
            map.put(in[i],i);     
        }
        return helper(pre,0,preLen-1,0,inLen-1);
    } 
    
    private TreeNode helper(int [] pre,int preL,int preR,int inL,int inR){
        //遍历结束条件
        if(preL>preR||inL>inR) return null;
        //首先找在pre中找根节点的值 并新建对应节点
        int val=pre[preL];
        TreeNode root=new TreeNode(val);
        //找到该节点值在in中的位置
        int index_in=map.get(val);
        //找到左子树 序列
        root.left=helper(pre,preL+1,preL+index_in-inL,inL,index_in-1);
        //右子树序列
        root.right=helper(pre,preL+index_in-inL+1,preR,index_in+1,inR);
        //返回根节点
        return root;        
    }
}

树的子结构||另一棵树的子树

解法时间复杂度空间复杂度
递归O(mn)O(m)
其他见题解
//递归
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A==null||B==null) return false;
        return helper(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B);
    }

    public boolean helper(TreeNode A, TreeNode B){
        if(B==null) return true;
        if(A==null||A.val!=B.val) return false;
        boolean left=helper(A.left,B.left);
        boolean right=helper(A.right,B.right);
        return left&&right; 
    }
}

二叉树的镜像||反转二叉树

解法时间复杂度空间复杂度
递归O(n)O(n)
辅助栈O(n)O(n)
public class Solution {
    public void Mirror(TreeNode root) {
        if(root==null) return;
        TreeNode tmp=root.right;
        root.right=root.left;
        root.left=tmp;
        Mirror(root.left);
        Mirror(root.right);
    }
}
class Solution {
    public TreeNode invertTree(TreeNode root) {
        //根不用转,左右子树递归
        if(root==null) return null;
        TreeNode left=invertTree(root.left);
        TreeNode right=invertTree(root.right);
        root.left=right;
        root.right=left;
        return root;
    }
}

从上到下打印二叉树①

解法时间复杂度空间复杂度
BFSO(n)O(n)
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> res=new ArrayList<>();//结果
        if(root==null) return res;
        
        Deque<TreeNode> deque=new ArrayDeque<>();
        deque.offer(root);
        while(!deque.isEmpty()){
            TreeNode first=deque.poll();
            res.add(first.val);
            if(first.left!=null){
                deque.offer(first.left);
            }
            if(first.right!=null){
                deque.offer(first.right);
            }
        }
        return res;
    }
}

把二叉树打印成多行||从上到下打印二叉树②

解法时间复杂度空间复杂度
BFSO(n)O(n)
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list=new ArrayList<>();
        if(root==null) return list;
        
        Deque<TreeNode> deque=new ArrayDeque<>();
        deque.offer(root);
        while(!deque.isEmpty()){
            List<Integer> tmp=new ArrayList<>();
            for(int i=deque.size();i>0;i--){//用 i++ 的话,每轮都要获取 queue.size() 的值,而队列的长度是在变化的
                TreeNode node=deque.poll();
                tmp.add(node.val);
                if(node.left!=null){
                    deque.offer(node.left);
                }
                if(node.right!=null){
                    deque.offer(node.right);
                }
            }
            list.add(tmp);
        }
        return list;
    }
}

按之字形顺序打印二叉树||从上到下打印二叉树③

解法时间复杂度空间复杂度
层序遍历 + 双端队列O(n)O(n)
层序遍历 + 双端队列(奇偶层逻辑分离)O(n)O(n)
层序遍历 + 倒叙O(n)
//层序遍历 + 双端队列
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list=new ArrayList<>();
        if(root==null) return list;
        
        Deque<TreeNode> deque=new ArrayDeque<>();
        deque.offer(root);
        while(!deque.isEmpty()){
            LinkedList<Integer> tmp=new LinkedList<>();//双端队列
            for(int i=deque.size();i>0;i--){//用 i++ 的话,每轮都要获取 queue.size() 的值,而队列的长度是在变化的
                TreeNode node=deque.poll();
                // tmp.add(node.val);
                if(list.size()%2==0) {//当前为奇数列,正序,后进前出
                    tmp.addLast(node.val);
                }else{//当前为偶数列,逆序,前进前出
                    tmp.addFirst(node.val);
                }
                if(node.left!=null){
                    deque.offer(node.left);
                }
                if(node.right!=null){
                    deque.offer(node.right);
                }
            }
            list.add(tmp); 
        }
        return list;
    }
}

二叉搜索树的后序遍历序列

解法时间复杂度空间复杂度
递归分治O(n^2)O(n)
单调栈O(n)O(n)

单调栈的方法没有看懂

//递归
class Solution {
    public boolean verifyPostorder(int[] postorder) {
        if(postorder==null||postorder.length==0) return true;
        int len=postorder.length;
        return recur(postorder,0,len-1);
    }

    private boolean recur(int[] postorder,int i,int j){
    //说明此子树节点数量 ≤1 ,无需判别正确性,因此直接返回 true
        if(i>=j) return true;
        int root=postorder[j];
        int p=i;//指针 从左到右
        while(postorder[p]<root) p++;
        //记录第一个大于root的下标
        int m=p;
        while(postorder[p]>root) p++;
        return p==j&&recur(postorder,i,m-1)&&recur(postorder,m,j-1);
    }
}

二叉树中和为某一值的路径||路径总和2

路径总和1

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null) return false;
        // int sum;
        sum-=root.val;
        // if(sum==0) return true;
        if(root.left==null&&root.right==null){//判断到达叶子节点
            return sum==0;//判断是否减到0
        }
        boolean left=hasPathSum(root.left,sum);
        boolean right=hasPathSum(root.right,sum);
        return left||right;
    }
}

路径总和3

路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)

public int pathSum(TreeNode root, int sum) {
        if(root==null) return 0;
        int res=getPathSum(root,sum);
        int left=pathSum(root.left,sum);
        int right=pathSum(root.right,sum);
        return res+left+right;
    }
    private int getPathSum(TreeNode root, int sum){
        if(root==null) return 0;
        sum-=root.val;
        int res=sum==0?1:0;
        return res+getPathSum(root.left,sum)+getPathSum(root.right,sum);
    }

二叉搜索树与双向链表

解法时间复杂度空间复杂度
递归(中序遍历)O(n)O(n)
class Solution {
    Node head, pre;//使用全局变量
    public Node treeToDoublyList(Node root) {
        if(root==null) return null;
        dfs(root);

        pre.right = head;
        head.left =pre;//进行头节点和尾节点的相互指向,这两句的顺序也是可以颠倒的

        return head;

    }

    public void dfs(Node cur){
        if(cur==null) return;
        dfs(cur.left);

        //pre用于记录双向链表中位于cur左侧的节点,即上一次迭代中的cur,当pre==null时,cur左侧没有节点,即此时cur为双向链表中的头节点
        if(pre==null) head = cur;
        //反之,pre!=null时,cur左侧存在节点pre,需要进行pre.right=cur的操作。
        else pre.right = cur;
       
        cur.left = pre;//pre是否为null对这句没有影响,且这句放在上面两句if else之前也是可以的。

        pre = cur;//pre指向当前的cur
        dfs(cur.right);//全部迭代完成后,pre指向双向链表中的尾节点
    }
}
方法一:非递归版
解题思路:
1.核心是中序遍历的非递归算法。
2.修改当前遍历节点与前一遍历节点的指针指向。
    import java.util.Stack;
    public TreeNode ConvertBSTToBiList(TreeNode root) {
        if(root==null)
            return null;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode p = root;
        TreeNode pre = null;// 用于保存中序遍历序列的上一节点
        boolean isFirst = true;
        while(p!=null||!stack.isEmpty()){
            while(p!=null){
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            if(isFirst){
                root = p;// 将中序遍历序列中的第一个节点记为root
                pre = root;
                isFirst = false;
            }else{
                pre.right = p;
                p.left = pre;
                pre = p;
            }      
            p = p.right;
        }
        return root;
    }
方法二:递归版
解题思路:
1.将左子树构造成双链表,并返回链表头节点。
2.定位至左子树双链表最后一个节点。
3.如果左子树链表不为空的话,将当前root追加到左子树链表。
4.将右子树构造成双链表,并返回链表头节点。
5.如果右子树链表不为空的话,将该链表追加到root节点之后。
6.根据左子树链表是否为空确定返回的节点。
    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null)
            return root;
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        TreeNode p = left;
        // 2.定位至左子树双链表最后一个节点
        while(p!=null&&p.right!=null){
            p = p.right;
        }
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left!=null){
            p.right = root;
            root.left = p;
        }
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }
方法三:改进递归版
解题思路:
思路与方法二中的递归版一致,仅对第2点中的定位作了修改,新增一个全局变量记录左子树的最后一个节点。
    // 记录子树链表的最后一个节点,终结点只可能为只含左子树的非叶节点与叶节点
    protected TreeNode leftLast = null;
    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null){
            leftLast = root;// 最后的一个节点可能为最右侧的叶节点
            return root;
        }
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left!=null){
            leftLast.right = root;
            root.left = leftLast;
        }
        leftLast = root;// 当根节点只含左子树时,则该根节点为最后一个节点
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }

二叉树的深度||二叉树的最大深度

解法时间复杂度空间复杂度
递归O(n)O(logn)
迭代O(n)O(n)
public class Solution {//递归
    public int TreeDepth(TreeNode root) {
        if(root==null) return 0;
        return Math.max(TreeDepth(root.left),TreeDepth(root.right))+1;
    }
}

平衡二叉树

解法时间复杂度空间复杂度
自顶向下O(logn)O(n)

平衡二叉树相关问题

//对于一颗树,它是一个平衡二叉树需要满足三个条件:
 //它的左子树是平衡二叉树;
 //它的右子树是平衡二叉树;
 //它的左右子树的高度差不大于1。
class Solution {
    public boolean isBalanced(TreeNode root) {
        return height(root)!=-1;
    }
    private int  height(TreeNode root){
        if(root==null) return 0;
        //不平衡的情况有3种:左树不平衡、右树不平衡、左树和右树差的绝对值大于1
        int leftheight=height(root.left);
        if(leftheight==-1) return -1;
        int rightheight=height(root.right);
        if(rightheight==-1) return -1;
        if(Math.abs(leftheight-rightheight)>=2)
            return -1;
        //不满足上面3种情况,说明平衡了,树的深度为左右俩子树最大深度+1
        return Math.max(leftheight,rightheight)+1;

    }
}

二叉树的下一个节点(未找到力扣对应题目)

public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        //中序遍历:左根右
        //情况1:当前节点为空,返回下一个节点null
        if(pNode==null) return null;
        //情况2:当前节点存在右子树,找右子树的最左叶子节点
        if(pNode.right!=null){
            pNode=pNode.right;
            while(pNode.left!=null){
                pNode=pNode.left;
            }
            return pNode;
        }
        //next 指向父节点
        //情况3:没有右子树 找父节点 直到 当前节点为父节点的左子节点
        while(pNode.next!=null){
            //
            if(pNode==pNode.next.left) return pNode.next;
            pNode=pNode.next;
        }
        
        return null;
    }
}

对称的二叉树

解法时间复杂度空间复杂度
递归O(n)O(n)
迭代O(n)O(n)
//递归
public class 对称二叉树 {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        boolean res=isSymmetric(root,root);
        return res;
    }
    private boolean isSymmetric(TreeNode leftNode,TreeNode rightNode){
        //递归终止:同时遍历到空节点 对称
        if(leftNode==null&&rightNode==null) return true;
        //只有一个遍历到了空 不对称
        if(leftNode==null||rightNode==null) return false;
        //本地递归操作:
        //判断当前节点左右子节点值相等 且左右子树对称
        return leftNode.val==rightNode.val&&isSymmetric(leftNode.left,rightNode.right)&&isSymmetric(leftNode.right,rightNode.left);
    }
}
//迭代
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root,root);
    }
    private boolean check(TreeNode leftNode,TreeNode rightNode){
        Queue<TreeNode> que=new LinkedList<>();
        que.offer(leftNode);
        que.offer(rightNode);
        while(!que.isEmpty()){
            leftNode=que.poll();
            rightNode=que.poll();
            if(leftNode==null&&rightNode==null) return true;
            if(leftNode==null||rightNode==null||leftNode.val!=rightNode.val) return false;
            que.offer(leftNode.left);
            que.offer(rightNode.right);
            que.offer(leftNode.right);
            que.offer(rightNode.left);
        }
        return true;
    }
}

序列化二叉树

困难

public class Solution {
    //设置全局
    //主要是遇到了#号的时候需要直接前进并返回null
    private int index=0;
    String Serialize(TreeNode root) {
        if(root==null) return "";
        return ser_helper(root,new StringBuilder()).toString();
  }
    public StringBuilder ser_helper(TreeNode root,StringBuilder s){
        if(root==null) return s;
        s.append(root.val).append("!");
        if(root.left!=null){
            ser_helper(root.left,s);
        }else{
            s.append("#!");//为null的话直接添加即可
        }
        if(root.right!=null){
            ser_helper(root.right,s);
        }else{
            s.append("#!");
        }
        return s;
    }
    TreeNode Deserialize(String str) {
       if(str==null||str.length()==0) return null;
        String[] word=str.split("!");
        return deser_helper(word);
  }
    
    TreeNode deser_helper(String[] strs){
        if(strs[index].equals("#")){
            index++;//数据前进
            return null;
        }
        //当前值作为节点已经被用
        TreeNode root=new TreeNode(Integer.valueOf(strs[index]));
        index++;//index到达下一个需要反序列化的值
        root.left=deser_helper(strs);
        root.right=deser_helper(strs);
        return root;
        
    }
}

/**不使用全局变量
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root==null) return "null";
        StringBuilder res=ser_helper(root,new StringBuilder());
        return res.toString();
        
        
    }

    public StringBuilder ser_helper(TreeNode root,StringBuilder str){
        if(root==null){
            str.append("null,");
            return str;
        }
        str.append(root.val).append(",");
        //str.append(",");
        str=ser_helper(root.left,str);
        str=ser_helper(root.right,str);
        return str;
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] str_word=data.split(",");
        List<String> list_word=new LinkedList<String>(Arrays.asList(str_word));
        return desre_helper(list_word);
    }

    public TreeNode desre_helper(List<String> list){
        if(list.get(0).equals("null")){
            list.remove(0);
            return null;
        }
        TreeNode cur=new TreeNode(Integer.valueOf(list.get(0)));
        list.remove(0);
        cur.left=desre_helper(list);
        cur.right=desre_helper(list);
        return cur;

    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

二叉搜索树的第K个节点|二叉搜索树的第k大节点

//迭代法 求第K小
import java.util.LinkedList;
public class Solution {
    TreeNode KthNode(TreeNode pRoot, int k)
    {
        if(pRoot==null) return null;
        if(k<=0) return null;
        LinkedList<TreeNode> stack=new LinkedList<>();
        TreeNode cur=pRoot;
        //中序遍历
        while(!stack.isEmpty()||cur!=null){
            if(cur!=null){
                stack.offerLast(cur);
                cur=cur.left;
            }else{
                cur=stack.pollLast();//按顺序输出最小值
                if(--k==0) return cur;
                cur=cur.right;
            }
        }
        return null;
    }


}
//中序遍历+倒序+提前返回 求第K大
 int count=0, res=0;//形参k不能随着dfs的迭代而不断变化,为了记录迭代进程和结果,引入类变量count和res。
  public int kthLargest(TreeNode root, int k) {
      this.count=k;//利用形参值k对类变量count进行初始化
      dfs(root);//这里不要引入形参k,dfs中直接使用的是初始值为k的类变量count
      return res;            
  }
  public void dfs(TreeNode root){
      if(root==null||count==0) return;//当root为空或者已经找到了res时,直接返回
      dfs(root.right);
      if(--count==0){//先--,再判断
          res = root.val;
          return;//这里的return可以避免之后的无效迭代dfs(root.left);
      }
      dfs(root.left);  
  }

回溯

深度优先遍历
树形
“回溯”算法也叫“回溯搜索”算法,“回溯”指的是“状态重置”,可以理解为“回到过去”、“恢复现场”,是在编码的过程中,是为了节约空间而使用的一种技巧。
而回溯其实是“深度优先遍历”特有的一种现象。之所以是“深度优先遍历”,是因为我们要解决的问题通常是在一棵树上完成的,在这棵树上搜索需要的答案,一般使用深度优先遍历。
在这里插入图片描述

题目 提示
47. 全排列 II 思考一下,为什么造成了重复,如何在搜索之前就判断这一支会产生重复,从而“剪枝”。 17 .电话号码的字母组合
22. 括号生成 这是字符串问题,没有显式回溯的过程。这道题广度优先遍历也很好写,可以通过这个问题理解一下为什么回溯算法都是深度优先遍历,并且都用递归来写。
39. 组合总和 使用题目给的示例,画图分析。
40. 组合总和 II
51. N皇后 其实就是全排列问题,注意设计清楚状态变量。
60. 第k个排列 利用了剪枝的思想,减去了大量枝叶,直接来到需要的叶子结点。
77. 组合 组合问题按顺序找,就不会重复。并且举一个中等规模的例子,找到如何剪枝,这道题思想不难,难在编码。
78. 子集 为数不多的,解不在叶子结点上的回溯搜索问题。解法比较多,注意对比。
90. 子集 II 剪枝技巧同 47 题、39 题、40 题。
93. 复原IP地址
784. 字母大小写全排列

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

写 backtrack 函数时,需要维护走过的「路径」和当前可以做的「选择列表」,当触发「结束条件」时,将「路径」记入结果集。

其实想想看,回溯算法和动态规划是不是有点像呢?我们在动态规划系列文章中多次强调,动态规划的三个需要明确的点就是「状态」「选择」和「base case」,是不是就对应着走过的「路径」,当前的「选择列表」和「结束条件」?

某种程度上说,动态规划的暴力求解阶段就是回溯算法。只是有的问题具有重叠子问题性质,可以用 dp table 或者备忘录优化,将递归树大幅剪枝,这就变成了动态规划。而今天的两个问题,都没有重叠子问题,也就是回溯算法问题了,复杂度非常高是不可避免的。

矩阵中的路径在这里插入图片描述

public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        if(matrix.length!=rows*cols) return false;
        char[][] board=new char[rows][cols];
        int count=0;
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                board[i][j]=matrix[count++];
            }
            
        }
        
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                if(dfs(board,i,j,str,0))
                    return true;
            }
        }
        return false;
    }
    
    private boolean dfs(char[][] board,int i,int j,char[] str,int index){
        if(i<0||i>=board.length||j<0||j>=board[0].length||board[i][j]!=str[index])
            return false;
        if(index==str.length-1) return true;
        char tmp=board[i][j];
        board[i][j]='/';
        boolean res=dfs(board,i+1,j,str,index+1)||dfs(board,i,j+1,str,index+1)||dfs(board,i-1,j,str,index+1)||dfs(board,i,j-1,str,index+1);
        board[i][j]=tmp;
        return res;
    }
}

典型的矩阵搜索问题

class Solution {
    public boolean exist(char[][] board, String word) {
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(dfs(board,word,i,j,0))
                    return true;
            }

        }
        return false;

    }

    private boolean dfs(char[][] borad, String word,int x,int y,int k){
        //先判断边界再判断值是否相等
        if(x>=borad.length||x<0||y>=borad[0].length||y<0||borad[x][y]!=word.charAt(k)) return false;
        if(k==word.length()-1) return true;
        char tmp=borad[x][y];
        borad[x][y]='*';
        //递归遍历 只需要一个跑通
        boolean res=dfs(borad,word,x+1,y,k+1)||dfs(borad,word,x-1,y,k+1)||dfs(borad,word,x,y+1,k+1)||dfs(borad,word,x,y-1,k+1);
        borad[x][y]=tmp;
        return res;
    }
}
 public static void main(String[] args) {

//        char[][] board =
//                {
//                        {'A', 'B', 'C', 'E'},
//                        {'S', 'F', 'C', 'S'},
//                        {'A', 'D', 'E', 'E'}
//                };
//
//        String word = "ABCCED";


        char[][] board = {{'a', 'b'}};
        String word = "ba";
        Solution solution = new Solution();
        boolean exist = solution.exist(board, word);
        System.out.println(exist);
    }

机器人的运动范围

public class Solution {
    int m,n,k;
    boolean[][] visited;
    public int movingCount(int threshold, int rows, int cols)
    {
        m=rows;n=cols;k=threshold;
        visited=new boolean[m][n];
        //
        return dfs(0,0,0,0);
    }
    
    public int dfs(int i,int j,int si,int sj){
        if(i>=m||j>=n||k<si+sj||visited[i][j]) return 0;
        visited[i][j]=true;
        return 1+dfs(i+1,j,(i+1)%10!=0?si+1:si-8,sj)+dfs(i,j+1,si,(j+1)%10!=0?sj+1:sj-8);
        
    }
}
import java.util.Queue;
import java.util.LinkedList;
public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        boolean[][] visited =new boolean[rows][cols];
        int res=0;
        Queue<int[]> queue=new LinkedList<int[]>();
       // Queue
        queue.add(new int[] {0,0,0,0});
        while(queue.size()>0){
            int[] elem=queue.poll();
            int x=elem[0],y=elem[1],sx=elem[2],sy=elem[3];
            if(x>=rows||y>=cols||threshold<sx+sy||visited[x][y]) continue;
            visited[x][y]=true;
            res++;
            queue.add(new int[] {x+1,y,(x+1)%10!=0?sx+1:sx-8,sy});
            queue.add(new int[] {x,y+1,sx,(y+1)%10!=0?sy+1:sy-8});
        }
        return res;
         
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值