ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

422,剑指 Offer-使用DFS和BFS解机器人的运动范围

2021-06-14 23:51:38  阅读:172  来源: 互联网

标签:10 格子 Offer int sum DFS BFS 访问 visited


watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

Knowing what you want is half the battle. Most people go through their whole lives not knowing what they want.

知道自己想要什么等于成功了一半,多数人一辈子浑浑噩噩也不知道自己想要什么。

问题描述

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。

 

例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

 

示例 1:

输入:m = 2, n = 3, k = 1

输出:3

示例 2:

输入:m = 3, n = 1, k = 0

输出:1

 

提示:

  • 1 <= n,m <= 100

  • 0 <= k <= 20

 

DFS(深度优先搜索)

这道题说的是一个机器人从左上角开始,他可以沿着上下左右四个方向走,并且走到的每个格子坐标的数字和不大于k,问可以走多少个格子。我们先来画个图看一下

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

这里统计的是能走多少个格子,所以统计肯定是不能有重复的,题中说了,机器人是可以沿着上下左右四个方向走的。但你想一下,任何一个格子你从任何一个方向进来(比如从上面进来),那么他只能往其他3个方向走,因为如果在往回走就重复了。但实际上我们只要沿着两个方向走就可以了,一个是右边,一个是下边,也就是上面图中红色的箭头。我们来看下代码

 1public int movingCount(int m, int n, int k) {
2    //临时变量visited记录格子是否被访问过
3    boolean[][] visited = new boolean[m][n];
4    return dfs(0, 0, m, n, k, visited);
5}
6
7public int dfs(int i, int j, int m, int n, int k, boolean[][] visited) {
8    //i >= m || j >= n是边界条件的判断,k < sum(i, j)判断当前格子坐标是否
9    // 满足条件,visited[i][j]判断这个格子是否被访问过
10    if (i >= m || j >= n || k < sum(i, j) || visited[i][j])
11        return 0;
12    //标注这个格子被访问过
13    visited[i][j] = true;
14    //沿着当前格子的右边和下边继续访问
15    return 1 + dfs(i + 1, j, m, n, k, visited) + dfs(i, j + 1, m, n, k, visited);
16}
17
18//计算两个坐标数字的和
19private int sum(int i, int j) {
20    int sum = 0;
21    while (i != 0) {
22        sum += i % 10;
23        i /= 10;
24    }
25    while (j != 0) {
26        sum += j % 10;
27        j /= 10;
28    }
29    return sum;
30}

 

BFS(广度优先搜索)

DFS是沿着一个方向一直往下走,有一种不撞南墙不回头的感觉,直到不满足条件才会回头。而BFS就显得有点博爱了,他不是一条道走下去,他会把离他最近的都访问一遍,访问完之后才开始访问第二近的……,一直这样下去,所以最好的一种数据结构就是使用队列,因为队列是先进先出,离他最近的访问完之后加入到队列中,最先入队的也是最先出队的,代码和上面有很多相似的地方,基本上没什么难度,来看下

 1public int movingCount(int m, int n, int k) {
2    //临时变量visited记录格子是否被访问过
3    boolean[][] visited = new boolean[m][n];
4    int res = 0;
5    //创建一个队列,保存的是访问到的格子坐标,是个二维数组
6    Queue<int[]> queue = new LinkedList<>();
7    //从左上角坐标[0,0]点开始访问,add方法表示把坐标
8    // 点加入到队列的队尾
9    queue.add(new int[]{0, 0});
10    while (queue.size() > 0) {
11        //这里的poll()函数表示的是移除队列头部元素,因为队列
12        // 是先进先出,从尾部添加,从头部移除
13        int[] x = queue.poll();
14        int i = x[0], j = x[1];
15        //i >= m || j >= n是边界条件的判断,k < sum(i, j)判断当前格子坐标是否
16        // 满足条件,visited[i][j]判断这个格子是否被访问过
17        if (i >= m || j >= n || k < sum(i, j) || visited[i][j])
18            continue;
19        //标注这个格子被访问过
20        visited[i][j] = true;
21        res++;
22        //把当前格子右边格子的坐标加入到队列中
23        queue.add(new int[]{i + 1, j});
24        //把当前格子下边格子的坐标加入到队列中
25        queue.add(new int[]{i, j + 1});
26    }
27    return res;
28}
29
30//计算两个坐标数字的和
31private int sum(int i, int j) {
32    int sum = 0;
33    while (i != 0) {
34        sum += i % 10;
35        i /= 10;
36    }
37    while (j != 0) {
38        sum += j % 10;
39        j /= 10;
40    }
41    return sum;
42}

 

总结

做这道题之前首先要明白DFS和BFS是什么意思,才能使用这两种方式。我们来画个图看一下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

假如从A点开始访问,DFS就是沿着一条道走下去,然后再走其他的道……。BFS就是图中先访问圈内的部分,然后再把圈放大继续访问……。

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

420,剑指 Offer-回溯算法解矩阵中的路径

419,剑指 Offer-旋转数组的最小数字

417,BFS和DFS两种方式求岛屿的最大面积

413,动态规划求最长上升子序列

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

长按上图,识别图中二维码之后即可关注。

 

如果喜欢这篇文章就点个"赞"吧

标签:10,格子,Offer,int,sum,DFS,BFS,访问,visited
来源: https://blog.51cto.com/u_4774266/2902841

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有