leetcode | 分类整理3(搜索)

本文详细介绍了 LeetCode 中搜索问题的三种主要策略:BFS(广度优先搜索)、DFS(深度优先搜索)和回溯。BFS 在无权图中求最短路径,DFS 用于可达性问题,回溯则用于排列组合问题。文章通过多个具体的 LeetCode 题目实例解析了每种策略的应用和关键点。
摘要由CSDN通过智能技术生成

搜索

BFS:广度优先

每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di <= dj。利用这个结论,可以求解最短路径等 最优解 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。

在程序实现 BFS 时需要考虑以下问题:

  • 队列:用来存储每一轮遍历得到的节点;
  • 标记:对于遍历过的节点,应该将它标记,防止重复遍历。

1) 每一层遍历的节点都与根节点距离相同:决定了什么时候path++:就是每遍历一层之前保留queue.size,这个size就是这一层的大小

2) 什么时候置flag?已经从队列中poll了之后

3) 最优解问题:因为每次遍历的都是和根节点距离相同的节点,所以最先到达终点的一定是最短路径

 

1091. 二进制矩阵中的最短路径(m)(经典BFS+visited)

重点:注意只有{0}一个数的情况

public int shortestPathBinaryMatrix(int[][] grid) {
        if(grid[0][0]==1 || grid[grid.length-1][grid[0].length-1]==1)
            return -1;
        if (grid.length == 1 && grid[0][0] == 0) {
            return 1;
        }
//        顺时针
        int[][] xOy = {
  {-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
//        int[][] xOy = {
  {1, 0}, {1, 1}, {1,-1}, {0, 1}, {0, -1}, {-1, 0},{-1, -1}, {-1, 1}};
        int n = grid.length;
        boolean[][] visited = new boolean[n][n];
        visited[0][0] = true;

        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {0,0});
        int pathLength = 0;

        while (!queue.isEmpty()) {
//            这一层节点的个数
            int size = queue.size();
            pathLength++;
            while (size-- > 0) {
                int[] node = queue.poll();
                int x = node[0];
                int y = node[1];
//                grid[x][y] = 1;
                for (int[] d : xOy) {
                    int nx = x + d[0];
                    int ny = y + d[1];

                    if (nx == n-1 && ny == n-1) {
                        return pathLength+1;
                    }

                    if (nx < 0 || nx >= n || ny < 0 || ny >= n || visited[nx][ny] || grid[nx][ny] == 1){
                        continue;
                    }

                    visited[nx][ny] = true;
                    queue.add(new int[] {nx,ny});
                }
            }
        }

        return -1;
    }

 

 

279. 完全平方数(m)

思路:

可以将每个整数看成图中的一个节点,如果两个整数之差为一个平方数,那么这两个整数所在的节点就有一条边。

要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。

本题也可以用动态规划求解,在之后动态规划部分中会再次出现。

完全平方数的规律:1,4,9,16.。。中间刚好相差(3,5,7,9....),即n^2-(n-1)^2 = 2n-1

public int numSquares(int n) {
        List<Integer> list = generateSquares(n);
        Queue<Integer> queue = new LinkedList<>();
        boolean[] visited = new boolean[n+1];

        queue.add(n);
        visited[n] = true;

        int level = 0;

        while (!queue.isEmpty()) {
            int size = queue.size();
            level++;
            while (size-- > 0) {
                int cur = queue.poll();
                for (int i: list
                     ) {
                    int next = cur - i;
//                    因为LinkedList是按顺序读,我们存的时候就是(1,4,9...)
                    if (next < 0) {
                        break;
                    }
                    if (next == 0) {
                        return level;
                    }

                    visited[next] = true;
                    queue.add(next);

                }
            }
        }

        return n;
    }

    /**
     * 生成小于 n 的平方数序列
     * @return 1,4,9,...
     */
    private List<Integer> generateSquares(int n) {
        List<Integer> squares = new ArrayList<>();
        int square = 1;
        int diff = 3;
        while (square <= n) {
            squares.add(square);
            square += diff;
            diff += 2;
        }
        return squares;
    }

 

127. 单词接龙(m)(重点!&#x

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值