0
点赞
收藏
分享

微信扫一扫

深&广度优先搜索

深&广度优先搜索

leetcode200岛屿数量

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

class Solution {
    char[][] grid;
    int M, N;

    public int numIslands(char[][] grid) {
        M = grid.length;
        if (M == 0) return 0;
        N = grid[0].length;
        if (N == 0) return 0;
        this.grid = grid;
        int num = 0;
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (grid[i][j] == '1') {
                    modify(i, j);
                    ++num;
                }
            }
        }
        return num;
    }

    private void modify(int i, int j) {
        if (i < 0 || i >= M || j < 0 || j >= N) return;
        if (grid[i][j] != '1') return;
        grid[i][j] = '2';
        modify(i + 1, j);
        modify(i - 1, j);
        modify(i, j - 1);
        modify(i, j + 1);
    }
}

leetcode695岛屿的最大面积

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

class Solution {
    int[][] grid;
    int M, N;

    public int maxAreaOfIsland(int[][] grid) {
        M = grid.length;
        N = grid.length;
        int res = 0;
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                res = Math.max(res, modify(i, j));
            }
        }
        return res;
    }

    private int modify(int i, int j) {
        if (i < 0 || i >= M || j < 0 || j >= N) return 0;
        if (grid[i][j] != '1') return 0;
        grid[i][j] = '0';
        int count = 0;
        count += modify(i + 1, j);
        count += modify(i - 1, j);
        count += modify(i, j - 1);
        count += modify(i, j + 1);
        return count;
    }
}

leetcode108将有序数组转化成二叉排序树

在这里插入图片描述

在这里插入图片描述

  • 主要是根节点的选择
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int[] arr;

    public TreeNode sortedArrayToBST(int[] nums) {
        this.arr = nums;
        return modify(0, arr.length-1);
    }

    private TreeNode modify(int left, int right) {
        if (left > right) return null;
        int mid = (right + left) / 2;
        TreeNode node = new TreeNode(arr[mid], modify(left, mid - 1), modify(mid + 1, right));
        return node;
    }
}

leetcode959由斜杠划分区域🔐

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

  • 深度优先搜索
class Solution {
    char[][] g;
    int N;

    public int regionsBySlashes(String[] grid) {
        N = grid.length * 3;
        g = new char[N][N];

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid.length; j++) {
                if (grid[i].charAt(j) == '\\')
                    g[i * 3][j * 3] = g[i * 3 + 1][j * 3 + 1] = g[i * 3 + 2][j * 3 + 2] = '1';
                else if (grid[i].charAt(j) == '/')
                    g[i * 3][j * 3 + 2] = g[i * 3 + 1][j * 3 + 1] = g[i * 3 + 2][j * 3] = '1';
            }
        }
        int count = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (g[i][j] != '1') {
                    dfs(i, j);
                    count++;
                }
            }
        }
        return count;
    }

    private void dfs(int i, int j) {
        if (i < 0 || i >= N || j < 0 || j >= N) return;
        if (g[i][j] == '1') return;
        g[i][j] = '1';
        dfs(i, j + 1);
        dfs(i, j - 1);
        dfs(i + 1, j);
        dfs(i - 1, j);
    }
}

在这里插入图片描述

  • 并查集
class Solution {
    public int regionsBySlashes(String[] grid) {
        int regions = 1;
        int N = grid.length;
        //每行节点数
        int nodesPerLine = N + 1;
        //N*N的图, 节点数是 (n+1) * (n+1)
        UnionFind uf = new UnionFind(nodesPerLine * nodesPerLine);
        for (int i = 0; i < N + 1; i++) {
            //把边都合并起来, 以2*2为例
            //合并0行,   0, 1, 2
            uf.union(0, i);
            //合并0列,   0, 3, 6
            uf.union(0, i * nodesPerLine);
            //合并最后行 6, 7, 8
            uf.union(N * nodesPerLine, N * nodesPerLine + i);
            //合并最后列 2, 5, 8
            uf.union(N, (i + 1) * nodesPerLine - 1);
        }

        for (int i = 0; i < N; i++) {
            char[] ca = grid[i].toCharArray();
            for (int j = 0; j < ca.length; j++) {
                char c = ca[j];
                //左上角点
                int leftTop = i * nodesPerLine + j;
                int top;
                int bottom;
                if (c == '/') {
                    top = leftTop + 1;
                    bottom = leftTop + nodesPerLine;
                } else if (c == '\\') {
                    top = leftTop;
                    bottom = leftTop + nodesPerLine + 1;
                } else {
                    continue;
                }
                if (!uf.union(top, bottom)) {
                    //合并失败 说明成环了, 这时候就 区域数 + 1
                    regions++;
                }
            }
        }
        return regions;
    }
    private static class UnionFind {
        private final int[] roots;
        public UnionFind(int n) {
            this.roots = new int[n];
            for (int i = 0; i < n; i++) {
                roots[i] = i;
            }
        }

        int findRoot(int i) {
            int root = roots[i];

            if (root == i) {
                return root;
            } else {
                roots[i] = findRoot(root);
                return roots[i];
            }
        }

        boolean union(int i, int j) {
            int root1 = findRoot(i);
            int root2 = findRoot(j);
            if (root1 != root2) {
                roots[root2] = root1;
                return true;
            }
            return false;
        }
    }
}

leetcode124二叉树中的最大路径和

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

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxNum = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        process(root);
        return maxNum;
    }

    private int process(TreeNode root) {
        if (root == null) return 0;
        int leftMax = Math.max(0, process(root.left));
        int rightMax = Math.max(0, process(root.right));
        maxNum = Math.max(maxNum, leftMax + rightMax + root.val);
        return Math.max(leftMax, rightMax) + root.val;
    }
}

leetcode99恢复二叉搜索树

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

  • 两种情况1.两个值相临2.不相邻
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    TreeNode tail_1, tail_2;

    public void recoverTree(TreeNode root) {
        process(root);
        int n = tail_1.val;
        tail_1.val = tail_2.val;
        tail_2.val = n;
    }

    TreeNode pre = null;

    private void process(TreeNode root) {
        if (root.left != null) process(root.left);
        if (pre!=null&&root.val <= pre.val) {
            if (tail_1 == null) tail_1 = pre;
            tail_2 = root;
        }
        pre = root;
        if (root.right != null) process(root.right);
    }
}

leetcode979在二叉树中分配硬币🔐

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

  • 转换成路径向上传递
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int res = 0;

    public int distributeCoins(TreeNode root) {
        process(root);
        return res;
    }

    private int process(TreeNode root) {
        if (root == null) return 0;
        int left = process(root.left);// 左边缺少或多出的个数
        int right = process(root.right);// 右边缺少或多出的个数
        res += Math.abs(left) + Math.abs(right);// 向root节点传递时,移动的步数
        return left + right + root.val - 1;// 整体缺少或多出的个数
    }
}

leetcode834树中距离之和🔐

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

  • 戳一戳 — >解题思路
class Solution {
    private List<List<Integer>> graph = new ArrayList<>();//邻接表
    int[] distSum; //距离和
    int[] nodeNum; //子树节点个数(包括自己)
    public int[] sumOfDistancesInTree(int N, int[][] edges) {

        for(int i = 0; i < N; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] edge : edges) {
            int src = edge[0];
            int dst = edge[1];
            graph.get(src).add(dst);
            graph.get(dst).add(src);
        }
        distSum = new int[N];
        nodeNum = new int[N];
        Arrays.fill(nodeNum, 1);
        postOrder(0, -1);
        preOrder(0, -1);
        return distSum;
    }
    //求root到子树所有节点的距离和
    private void postOrder(int root, int parent) {
        List<Integer> neighbors = graph.get(root);
        for(Integer neighbor : neighbors) {
            if(neighbor == parent)
                continue; //如果邻接点是父节点,则跳过
            postOrder(neighbor, root);
            nodeNum[root] += nodeNum[neighbor];
            distSum[root] += distSum[neighbor] + nodeNum[neighbor];
        }
    }
    //根据root计算其邻居到所在子树之外的节点的距离和(包括root节点)
    private void preOrder(int root, int parent) {
        List<Integer> neighbors = graph.get(root);
        for(Integer neighbor : neighbors) {
            if(neighbor == parent)
                continue;
            // 这转化看似平平无奇,实际上是动态存储的思想,这样就可以只使用一个公式解决了,不用记录路径长度
            distSum[neighbor] = distSum[root] - nodeNum[neighbor] + (graph.size() - nodeNum[neighbor]);
            preOrder(neighbor, root);
        }
    }
}

leetcode102二叉树的层序遍历

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List list = new ArrayList<List<Integer>>();
        if (root == null) return list;
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        TreeNode pre = root;
        TreeNode next = null;
        List<Integer> o = new ArrayList<>();
        while (!queue.isEmpty()) {
            TreeNode x = queue.poll();
            o.add(x.val);
            if (x.left != null) {
                queue.add(x.left);
                next = x.left;
            }
            if (x.right != null) {
                queue.add(x.right);
                next = x.right;
            }
            if (x == pre) {
                list.add(o);
                o = new ArrayList<>();
                pre = next;
                next = null;
            }
        }
        return list;
    }
    
}

leetcode107二叉树的层序遍历2

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List list = new ArrayList<List<Integer>>();
        if (root == null) return list;
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        TreeNode pre = root;
        TreeNode next = null;
        List<Integer> o = new ArrayList<>();
        while (!queue.isEmpty()) {
            TreeNode x = queue.poll();
            o.add(x.val);
            if (x.left != null) {
                queue.add(x.left);
                next = x.left;
            }
            if (x.right != null) {
                queue.add(x.right);
                next = x.right;
            }
            if (x == pre) {
                list.add(0,o);
                o = new ArrayList<>();
                pre = next;
                next = null;
            }
        }
        return list;
    }
}

leetcode199二叉树的右视图

在这里插入图片描述

在这里插入图片描述

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;
        TreeNode thisFloorLastNode = root;
        TreeNode nextFloorLastNode = null;
        Queue<TreeNode> deque = new ArrayDeque<>();
        deque.add(root);
        while (!deque.isEmpty()) {
            TreeNode x = deque.poll();
            if (x.left != null) {
                deque.add(x.left);
                nextFloorLastNode = x.left;
            }
            if (x.right != null) {
                deque.add(x.right);
                nextFloorLastNode = x.right;
            }
            if (x == thisFloorLastNode) {
                list.add(x.val);
                thisFloorLastNode = nextFloorLastNode;
                nextFloorLastNode = null;
            }
        }
        return list;
    }
}

leetcode114二叉树展开为链表🔐

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

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public void flatten(TreeNode root) {
        root = process(root);
    }

    private TreeNode process(TreeNode root) {
        if (root == null) return null;
        TreeNode l = process(root.left);
        TreeNode r = process(root.right);
        root.left = null;
        root.right = l;
        if (l != null) {
            while (l.right != null) {
                l = l.right;
            }
            l.right = r;
        } else {
            root.right = r;
        }
        return root;
    }
}

leetcode109有序链表转换成二叉搜索树

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

  • 根本上还是分治思想
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if (head == null) return null;
        if (head.next == null) return new TreeNode(head.val);
        if (head.next.next==null)return new TreeNode(head.next.val,new TreeNode(head.val),null);
        ListNode pre = null, slow = head, quick = head;
        while (quick.next != null && quick.next.next != null) {
            pre = slow;
            slow = slow.next;
            quick = quick.next.next;
        }
        if (pre != null)
            pre.next = null;
        TreeNode node = new TreeNode(slow.val);
        node.left = sortedListToBST(head);
        node.right = sortedListToBST(slow.next);
        return node;

    }
}

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

在这里插入图片描述

在这里插入图片描述

  • 最开始用的层序遍历
class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        Node thisFloorLastNode = root;
        Node nextFloorLastNode = null;
        Node pre= root;
        Queue<Node> deque = new ArrayDeque<>();
        deque.add(root);
        while (!deque.isEmpty()) {
            Node x = deque.poll();
            if (x.left != null) {
                deque.add(x.left);
                nextFloorLastNode = x.left;
                pre.next=x.left;
                pre=x.left;
            }
            if (x.right != null) {
                deque.add(x.right);
                nextFloorLastNode = x.right;
                pre.next=x.right;
                pre=x.right;
            }
            if (x == thisFloorLastNode) {
                thisFloorLastNode = nextFloorLastNode;
                nextFloorLastNode = null;
                x.next=null;
            }
        }
        return root;
    }
}

在这里插入图片描述

  • 递归实现(太妙了)
class Solution {
    public Node connect(Node root) {
        if (root == null || root.left == null) return root;
        root.left.next = root.right;
        if (root.next != null)
            root.right.next = root.next.left;
        connect(root.left);
        connect(root.right);
        return root;
    }
}

leetcode279完全平方数

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

  • 经典DP
class Solution {
    public int numSquares(int n) {
        int maxN = (int) Math.sqrt(n);
        int[][] dp = new int[maxN + 2][n + 1];

        for (int i = 0; i <= n; i++) {
            dp[maxN + 1][i] = 10;
        }
        for (int i = 0; i <= maxN + 1; i++) {
            dp[i][0] = 0;
        }
        for (int i = maxN; i > 0; i--) {
            for (int j = 1; j <= n; j++) {
                int thisNum = 10;
                for (int x = 0; i * i * x <= j; x++) {
                    thisNum = Math.min(thisNum, x + dp[i + 1][j - i * i * x]);
                }
                dp[i][j] = thisNum;
            }
        }
        return dp[1][n];
    }
}

在这里插入图片描述

  • 压缩DP
class Solution {
    public int numSquares(int n) {
        int maxN = (int) Math.sqrt(n);
        int[] dp = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            dp[i] = 10;
        }
        for (int i = maxN; i > 0; i--) {
            for (int j = 1; j <= n; j++) { 
                if (i * i <= j) {
                    dp[j] = Math.min(dp[j - i * i] + 1, dp[j]);
                }
            }
        }
        return dp[n];
    }
}

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

class Solution {
    public int numSquares(int n) {
        if (isPerfectSquare(n)) {
            return 1;
        }
        if (checkAnswer4(n)) {
            return 4;
        }
        for (int i = 1; i * i <= n; i++) {
            int j = n - i * i;
            if (isPerfectSquare(j)) {
                return 2;
            }
        }
        return 3;
    }

    // 判断是否为完全平方数
    public boolean isPerfectSquare(int x) {
        int y = (int) Math.sqrt(x);
        return y * y == x;
    }

    // 判断是否能表示为 4^k*(8m+7)
    public boolean checkAnswer4(int x) {
        while (x % 4 == 0) {
            x /= 4;
        }
        return x % 8 == 7;
    }
}

leetcode101对称二叉树

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

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null)return true;
        return pro(root.left,root.right);
    }
    boolean pro(TreeNode r1,TreeNode r2){
        if(r1==null&&r2==null)return true;
         if(r1==null||r2==null)return false;
         return r1.val==r2.val&&pro(r1.right,r2.left)&&pro(r1.left,r2.right);
    }
}

leetcode133克隆图

在这里插入图片描述

在这里插入图片描述

  • 注意map.put位置,要在深搜访问处put
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> neighbors;
    public Node() {
        val = 0;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val) {
        val = _val;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val, ArrayList<Node> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
}
*/

class Solution {
    HashMap<Node, Node> map;
    public Node cloneGraph(Node node) {
        map = new HashMap<>();
        if(node==null)return map;
        dfs(node);
        return map.get(node);
    }

    private void dfs(Node node) {
        if (map.containsKey(node)) return;
        map.put(node, new Node(node.val, new ArrayList<>()));
        for (Node n : node.neighbors) {
            dfs(n);
            map.get(node).neighbors.add(map.get(n));
        }
    }
}

leetcode103二叉树的锯齿形层序遍历🔐

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

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        ArrayList<List<Integer>> lists = new ArrayList<>();
        if (root == null) {
            return lists;
        }
        // 创建两个栈结构
        Stack<TreeNode>[] stack = new Stack[]{new Stack<>(), new Stack<>()};
        int current = 0;// 当前需要遍历的层需要的栈索引
        int next = 1;// 遍历(删除)stack[current]时,填充stack[next]位置的栈空间
        stack[current].push(root);// 将根节点放入当前栈中
        List<Integer> l=new ArrayList<>();
        while (!stack[0].isEmpty() || !stack[1].isEmpty()) {

            TreeNode tempNode = stack[current].pop();
            l.add(tempNode.val);
            // 由于遍历不同层所需要的填入stack[next]顺序不同,所以要分开。
            if (current == 0) {
                // 不为空就要入栈
                if (tempNode.left != null) {
                    stack[next].push(tempNode.left);
                }
                if (tempNode.right != null) {
                    stack[next].push(tempNode.right);
                }
            } else {
                // 不为空就要入栈
                if (tempNode.right != null) {
                    stack[next].push(tempNode.right);
                }
                if (tempNode.left != null) {
                    stack[next].push(tempNode.left);
                }
            }
            // 若当前栈空,说明该层节点结束,进行遍历另一个栈结构
            if (stack[current].isEmpty()) {
                lists.add(l);
                l=new ArrayList<>();
                // 转换栈结构的索引
                current = 1 - current;
                next = 1 - next;
            }
        }
        return  lists;
    }

}

leetcode111二叉树的最小深度

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

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        int l = minDepth(root.left), r = minDepth(root.right);
        // 若又一边为0表示一边为空,返回不为零的,若均不为0,就返回最小的一方
        return (l == 0 || r == 0 ? Math.max(l, r) : Math.min(l, r)) + 1;
    }
}

leetcode130被环绕的区域

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

class Solution {
    char[][] grid;
    int M,N;
    public void solve(char[][] board) {
        grid = board;
        M = grid.length;
        N = grid[0].length;
        for (int i = 0; i < M; i++) {
            dfs(i, 0);
            dfs(i, N - 1);
        }
        for (int j = 1; j < N - 1; j++) {
            dfs(0, j);
            dfs(M - 1, j);
        }
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (grid[i][j] == 'O') {
                    grid[i][j] = 'X';
                } else if (grid[i][j] == 'A') {
                    grid[i][j] = 'O';
                }
            }
        }
        
    }

    private void dfs(int i, int j) {
        if(i<0||i>=M||j<0||j>=N)return;
        if (grid[i][j] != 'O') return;
        grid[i][j] = 'A';
        dfs(i, j + 1);
        dfs(i, j - 1);
        dfs(i + 1, j);
        dfs(i - 1, j);
    }
}

leetcode52401矩阵

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

  • 贪心思想
  • 若用深搜广搜就要从每一个0为起始位置进行深广搜。过程中记录数据最小值即可
class Solution {
    public int[][] updateMatrix(int[][] mat) {
        int M = mat.length;
        if (M==0)return mat;
        int N = mat[0].length;
        if (N==0)return mat;
        mat[0][0] = mat[0][0] == 0 ? 0 : 100000;
        for (int i = 1; i < N; i++) {
            mat[0][i] = mat[0][i] == 1 ? mat[0][i - 1] + 1 : 0;
        }
        for (int i = 1; i < M; i++) {
            mat[i][0] = mat[i][0] == 1 ? mat[i - 1][0] + 1 : 0;
        }
        for (int i = 1; i < M; i++) {
            for (int j = 1; j < N; j++) {
                mat[i][j] = mat[i][j] == 1 ? Math.min(mat[i][j - 1], mat[i - 1][j]) + 1 : 0;
            }
        }

        for (int i = N - 2; i >= 0; i--) {
            mat[M - 1][i] = mat[M - 1][i] == 0 ? 0 : Math.min(mat[M - 1][i], mat[M - 1][i + 1] + 1);
        }
        for (int j = M - 2; j >= 0; j--) {
            mat[j][N - 1] = mat[j][N - 1] == 0 ? 0 : Math.min(mat[j][N - 1], mat[j + 1][N - 1] + 1);
        }
        for (int i = M - 2; i >= 0; i--) {
            for (int j = N - 2; j >= 0; j--) {
                mat[i][j] = mat[i][j] == 0 ? 0 : Math.min(mat[i][j], Math.min(mat[i][j + 1], mat[i + 1][j]) + 1);
            }
        }
        return mat;
    }
}

leetcode529扫雷游戏

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

class Solution {
    private int n, m;
    private char[][] matix;
    // 相邻的方块坐标、左、右、下、上、左上、右上、左下、右下
    int[] X = {0, 0, -1, 1, -1, -1, 1, 1};
    int[] Y = {-1, 1, 0, 0, -1, 1, -1, 1};

    public char[][] updateBoard(char[][] board, int[] click) {
        int x = click[0], y = click[1];
        n = board.length;
        m = board[0].length;
        this.matix = board;
        // 若为 E 则 搜索
        if (matix[x][y] == 'E') dfs(x, y);
            // 若为 M 则 标记为 X 、游戏结束
        else if (matix[x][y] == 'M') matix[x][y] = 'X';
        return matix;
    }

    public void dfs(int i, int j) {
        // 检查坐标是否 合理
        if (!check(i, j) || matix[i][j] != 'E') return;
        // 首先查找相邻方块的炸弹数
        int num = findM(i, j);
        // 无炸弹,标记为 B、 继续递归相邻方块
        if (num == 0) {
            matix[i][j] = 'B';
            for (int p = 0; p < 8; ++p)
                dfs(i + X[p], j + Y[p]);
        } else {// 有炸弹, 标记为周围的炸弹数
            matix[i][j] = (char) (num + 48);
        }

    }

    // 判断坐标是否合理
    public boolean check(int i, int j) {
        return i >= 0 && j >= 0 && i < n && j < m;
    }

    // 查找周围的炸弹数
    public int findM(int i, int j) {
        // 上下左右 、 对角线
        int ans = 0;
        for (int p = 0; p < 8; ++p)
            if (check(i + X[p], j + Y[p]) && matix[i + X[p]][j + Y[p]] == 'M')
                ++ans;
        return ans;
    }
}

leetcode524通过删除字母匹配到字典里最长单词

在这里插入图片描述

在这里插入图片描述

class Solution {
    public String findLongestWord(String s, List<String> dictionary) {
        String res = "";
        for (String each : dictionary) {
            if (res.length() > each.length()) continue;
            if (isVaild(s, each)) {
                if (!(res.length() == each.length() && res.compareTo(each) < 0)) {
                    res = each;
                }
            }
        }
        return res;
    }

    private boolean isVaild(String s, String each){
        int i = 0;
        int j = 0;
        while (i < s.length() && j < each.length()) {
            while (i < s.length() && s.charAt(i) != each.charAt(j)) {
                i++;
            }
            if (i==s.length())return false;// 出现越界,就结束,若没有这句话,若在此时j==each.length()-1,并且未匹配成功,经过后面j++,就会造成结果错误
            i++;
            j++;
        }
        return j == each.length();
    }
}

leetcode207课程表🔐

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

  • 本质是宽度优先搜索,通过遍历每次的入度进行判断,也是大学里教的,但是是最慢的方法
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int[] inNum = new int[numCourses];
        for (int[] i : prerequisites) {
            inNum[i[0]]++;// 记录入度
        }
        Queue<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < numCourses; i++) {
            if (inNum[i] == 0) {
                queue.add(i);// 将入度为0的进入队列
            }
        }
        int num = 0;
        while (!queue.isEmpty()) {
            int pop = queue.poll();// 删除课程表示当前可以做的
            num++;
            for (int[] prerequisite : prerequisites) {//pop为谁的前驱,就减一,造成新课程入度为零就入队列
                if (prerequisite[1] == pop) {
                    inNum[prerequisite[0]]--;
                    if (inNum[prerequisite[0]] == 0) {
                        queue.add(prerequisite[0]);
                    }
                }
            }
        }
        return num == numCourses;
    }
}

在这里插入图片描述

  • 深度优先搜索,判断有无环的经方式
class Solution {
    boolean res = true;
    int[] isVisited;
    List<List<Integer>> list;// 下标为课程,内部List为后继结点

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        list = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            list.add(new ArrayList<>());
        }
        // 建图
        for (int[] i : prerequisites) {
            list.get(i[1]).add(i[0]);
        }
        isVisited = new int[numCourses];
        for (int i = 0; i < numCourses && res; i++) {
            if (isVisited[i] == 0) {
                dfs(i);
            }
        }
        return res;
    }

    private void dfs(int i) {
        isVisited[i] = 1;// 标记,说明为1时指该条路经上正在深搜的边
        for (int x : list.get(i)) {
            if (isVisited[x] == 0) {
                dfs(x);
            } else if (isVisited[x] == 1) {// 回到了该条路上深搜的边,说明有环不能上完
                res = false;
                return;
            }
        }
        // 标记2表示该路劲已经遍历,并且从该点出发无环
        isVisited[i] = 2;
    }
}

leetcode847访问所有节点的最短路径🔐🔐

在这里插入图片描述

在这里插入图片描述

class Solution {
    public int shortestPathLength(int[][] graph) {
        int n = graph.length;

        // 1.初始化队列及标记数组,存入起点
        Queue<int[]> queue = new LinkedList<>(); // 三个属性分别为 idx, mask, dist
        boolean[][] vis = new boolean[n][1 << n]; // 节点编号及当前状态
        for (int i = 0; i < n; i++) {
            //存入起点(指向方向作用),标记(已经走过的节点记录),从起始节点走过标记节点并且到i的距离
            queue.offer(new int[]{i, 1 << i, 0});
            vis[i][1 << i] = true;
        }

        // 开始搜索
        while (!queue.isEmpty()) {
            int[] tuple = queue.poll(); // 弹出队头元素
            int idx = tuple[0], mask = tuple[1], dist = tuple[2];

            // 找到答案,返回结果
            if (mask == (1 << n) - 1) return dist;

            // 扩展
            for (int x : graph[idx]) {
                int next_mask = mask | (1 << x);
                if (!vis[x][next_mask]) {// 若存在,说明定存在有一条其他最优路路,距离不超过dist
                    queue.offer(new int[]{x, next_mask, dist + 1});
                    vis[x][next_mask] = true;
                }
            }
        }
        return 0;
    }
}

leetcode773滑动谜题🔐

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

  • 宽度优先搜索
class Solution {
    class Node {
        //当前 board 对应的字符串,例如 [[1,2,3],[4,5,0]] ==> 123450, 采用典型的二维数组映射到一维数组的方式
        String str;
        //当前 board 中 0 的横纵坐标
        int row, column;

        Node(String str, int row, int column) {
            this.str = str;
            this.row = row;
            this.column = column;
        }
    }

    // 2 X 3 的板
    int rows = 2;
    int columns = 3;
    // 输入的 board 转化后得到的字符串
    String inputStr;
    // 目标字符串
    String targetStr = "123450";
    // 输入的 board 中 0 的横、纵坐标
    int initRow, initColumn;

    // 方向数组
    int[][] dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    public int slidingPuzzle(int[][] board) {
        inputStr = "";
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                inputStr += board[i][j];
                if (board[i][j] == 0) {
                    initRow = i;
                    initColumn = j;
                }
            }
        }
        int ans = bfs();
        return ans;
    }

    int bfs() {
        Queue<Node> queue = new LinkedList<>();
        //记录由原字符串(即输入的 board 转化成的初始字符串)滑动到当前字符串需要移动的次数
        Map<String, Integer> map = new HashMap<>();

        //典型 bfs 算法,把初始节点添加到队列中
        Node root = new Node(inputStr, initRow, initColumn);
        queue.offer(root);
        // 从 inputStr 滑动到 inputStr 需要移动 0 次
        map.put(inputStr, 0);

        while (!queue.isEmpty()) {
            Node poll = queue.poll();
            int step = map.get(poll.str);
            //取出队列头节点,如果节点中的字符串已经满足条件,则直接返回
            if (poll.str.equals(targetStr)) return step;
            //获取节点字符串中 0 元素的横、纵坐标,分别尝试和四个方向的元素交互位置
            int currRow = poll.row, currColumn = poll.column;
            for (int[] dir : dirs) {
                int nextRow = currRow + dir[0], nextColumn = currColumn + dir[1];
                //如果下标越界,跳过本次循环
                if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns) continue;
                // 交换 board[currRow][currColumn] 和 board[nextRow][nextColumn]
                String newStr = update(poll.str, currRow, currColumn, nextRow, nextColumn);
                // 如果已经处理过 newStr ,则跳过本次循环
                if (map.containsKey(newStr)) continue;
                //构建新节点并放入队列中,等待下一轮处理
                Node next = new Node(newStr, nextRow, nextColumn);
                queue.offer(next);
                //更新从 inputStr 到 newStr 的滑动次数
                map.put(newStr, step + 1);
            }

        }
        return -1;
    }

    /**
     * 交换 board[currRow][currColumn] 和 board[nextRow][nextColumn], 采用典型的二维数组映射到一维数组的方式
     */
    String update(String cur, int currRow, int currColumn, int nextRow, int nextColumn) {
        char[] cs = cur.toCharArray();
        char tmp = cs[currRow * columns + currColumn];
        cs[currRow * columns + currColumn] = cs[nextRow * columns + nextColumn];
        cs[nextRow * columns + nextColumn] = tmp;
        return String.valueOf(cs);
    }
}
举报

相关推荐

0 条评论