leetcode刷题第22天——2000,1091,130,797

第二十二天

2000 反转单词前缀

给你一个下标从0开始的字符串word和一个字符ch 。找出ch 第一次出现的下标i ,反转word中从下标0 开始、直到下标i结束(含下标i )的那段字符。如果word 中不存在字符ch ,则无需进行任何操作。

例如,如果 word = "abcdefd"ch = "d" ,那么你应该 反转 从下标0开始、直到下标3结束(含下标3)。结果字符串将会是 "dcbaefd"
返回 结果字符串 。

方法

从头往后扫,找到目标字符,反转即可。

class Solution {
    public String reversePrefix(String word, char ch) {
        int end = -1;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < word.length(); ++i){
            sb.append(word.charAt(i));
            if (word.charAt(i) == ch) {
                end = i;
                break;
            }
        }
        if (end == -1) return sb.toString();
        return sb.reverse().toString() + word.substring(end + 1, word.length());
    }
}

1091 二进制矩阵中的最短路径

给你一个n x n 的二进制矩阵 grid中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回-1

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

路径途经的所有单元格都的值都是 0
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。

方法 BFS

从开始节点开始,进行广度优先搜索,每次判断时记录当前的step,当到目标位置时,直接返回step值即可。注意边界条件的判断,开始位置不能为1,以及如果找不到这个答案,也需要返回-1

class Solution {
    public static boolean[][] isVisited;
    public static int[] dirX = {0, 0, 1, -1, 1, 1, -1, -1};//八个方向
    public static int[] dirY = {1, -1, 0, 0, 1, -1, 1, -1};

    public int shortestPathBinaryMatrix(int[][] grid) {
        if (grid[0][0] == 1) return -1;
        if (grid[0][0] == 0 && grid.length == 1) return 1;
        int res = -1;
        int length = grid.length;
        isVisited = new boolean[length][length];
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{0, 0, 1});
        while (!queue.isEmpty()){
            int[] temp = queue.poll();
            int x = temp[0];
            int y = temp[1];
            int step = temp[2];
            isVisited[x][y] = true;
            for (int i = 0; i < 8; ++i) {
                int newX = x + dirX[i];
                int newY = y + dirY[i];
                int newStep = step + 1;
                if (newX >= 0 && newX < length && newY >= 0 && newY < length
                && !isVisited[newX][newY] && grid[newX][newY] == 0){
                    queue.offer(new int[]{newX, newY, newStep});
                    isVisited[newX][newY] = true;
                    if (newX == length - 1 && newY == length - 1) return newStep;
                }
            }
        }
        return res;
    }
}

130 被包围的区域

给你一个 m x n 的矩阵 board,由若干字符'X''O',找到所有被 'X' 围绕的区域,并将这些区域里所有的'O''X'填充。

方法

使用广度优先搜索处理这个问题,具体的方法是首先将边界上的O全部找出来,然后将其加入到带访问的队列中去,然后以这个队列为基础开始BFS。将所有经过的点都标记为true,返回答案时,将标记为true的位置置为O,其他地方置为X

class Solution {
    public static boolean[][] isVisited;
    public static int[] dX = {0, 0, 1, -1};
    public static int[] dY = {1, -1, 0, 0};

    public void solve(char[][] board) {
        Queue<int[]> queue = new LinkedList<>();
        int xLength = board.length;
        int yLength = board[0].length;
        isVisited = new boolean[xLength][yLength];
        for (int i = 0; i < yLength; ++i) {
            if (board[0][i] == 'O' && !isVisited[0][i]) {
                queue.offer(new int[]{0, i});
                isVisited[0][i] = true;
            }
            if (board[xLength - 1][i] == 'O' && !isVisited[xLength - 1][i]) {
                queue.offer(new int[]{xLength - 1, i});
                isVisited[xLength - 1][i] = true;
            }

        }
        for (int i = 0; i < xLength; ++i) {
            if (board[i][0] == 'O' && !isVisited[i][0]) {
                queue.offer(new int[]{i, 0});
                isVisited[i][0] = true;
            }
            if (board[i][yLength - 1] == 'O' && !isVisited[i][yLength - 1]) {
                queue.offer(new int[]{i, yLength - 1});
                isVisited[i][yLength - 1] = true;
            }
        }
        while (!queue.isEmpty()){
            int[] temp = queue.poll();
            int x = temp[0];
            int y = temp[1];
            isVisited[x][y] = true;
            for (int i = 0; i < 4; ++i){
                int newX = x + dX[i];
                int newY = y + dY[i];
                if (newX >= 0 && newX < xLength && newY >= 0 && newY < yLength
                && !isVisited[newX][newY] && board[newX][newY] == 'O') {
                    queue.offer(new int[]{newX, newY});
                    isVisited[newX][newY] = true;
                }
            }
        }
        for (int i = 0; i < xLength; ++i) {
            for (int j = 0; j < yLength; ++j) 
                if (isVisited[i][j]) board[i][j] = 'O';
                else board[i][j] = 'X';
        }
    }
}

797 所有可能的路径

给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点0 到节点n-1的路径并输出(不要求按特定顺序)

graph[i]是一个从节点i可以访问的所有节点的列表(即从节点 i到节点 graph[i][j]存在一条有向边)。

方法

这是一道回溯题,当访问到某一个节点时,首先将这个节点标记为已访问,回溯时,将这个节点重新标记为未访问即可,同时维护一个array用于保存结果。

class Solution {
    
    public static int n;
    public static boolean[] isUsed;
    public static ArrayList<Integer> route;
    public static List<List<Integer>> res;

    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        n = graph.length;
        route = new ArrayList<>();
        isUsed = new boolean[n];
        res = new ArrayList<>();
        deepFirstSearch(0, graph);
        return res;
    }

    public static void deepFirstSearch(int current, int[][] graph){
        int[] toBeVisited = graph[current];
        route.add(current);
        if (current == n - 1){
            res.add(new ArrayList<>(route));
            return;
        }
        for (int i :  toBeVisited){
            if (!isUsed[i]){
                isUsed[i] = true;
                deepFirstSearch(i, graph);
                isUsed[i] = false;
                route.remove(route.size() - 1);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值