Leetcode每日一题(13. 机器人的运动范围)

13. 机器人的运动范围
前言
  • 由于本人入职准备,以及其他的杂七杂八事项,导致之前停更了好几天的leetcode做题。自己也非常愧疚,今日开始正常更新leetcode的每日一题。哎,生活难,难生活。
题目
  • 地上有一个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。请问该机器人能够到达多少个格子?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例 1:

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

示例 1:

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

1.分析
  • 首先根据题目大意,题中提供了一个m*n的矩阵。在矩阵上有一个机器人,每次机器人的移动方位只能是上下左右,以及边界不能移动。
  • 在机器人移动的过程中,我们要保证题目中给出的条件,在满足条件的情况下,累加机器人走过了几个位置。最终返回的结果就是题目中要求的解体答案。
  • 注:题目中明确给出了,条件[x,y]------x+y <= k,如果x,y分别为10位数,就要将x,y分解每个位置的数相加与k作比较。
2.设计
  • 这种矩阵+条件,即为矩阵搜索问题,在遇到这类问题,一般的解决思路为BFS/DFS。也就是广度/深度优先搜索。
  • 首先解决x,y中个位置数相加的结果。
  • DFS—>DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
    • 递归参数: 当前元素在矩阵中的行列索引 i 和 j ,两者的数位和 si, sj 。

    • 终止条件: 当 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,返回 000 ,代表不计入可达解。
      递推工作:

    • 标记当前单元格 :将索引 (i, j) 存入 Set visited 中,代表此单元格已被访问过。

    • 搜索下一单元格: 计算当前元素的 下、右 两个方向元素的数位和,并开启下层递归 。

    • 回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。

  • BFS—>BFS 以“平推”的方式向前搜索,通常BFS的解决是利用辅助队列
    • 初始化: 将机器人初始点 (0,0)(0, 0)(0,0) 加入队列 queue ;
      迭代终止条件: queue 为空。代表已遍历完所有可达解。
      迭代工作:

    • 单元格出队: 将队首单元格的 索引、数位和 弹出,作为当前搜索单元格。

    • 判断是否跳过: 若 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,执行 continue 。

    • 标记当前单元格 :将单元格索引 (i, j) 存入 Set visited 中,代表此单元格 已被访问过 。

    • 单元格入队: 将当前元素的 下方、右方 单元格的 索引、数位和 加入 queue 。

    • 返回值: Set visited 的长度 len(visited) ,即可达解的数量。

3.实现
package com.iamasd;

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author EDZ
 * 面试题13. 机器人的运动范围
 */
public class Test1 {
    

    public static void main(String[] args) {
        int i = movingCountBFS(16, 8, 4);
        System.out.println(i);
    }

    /**
     * BFS
     * @param m
     * @param n
     * @param k
     * @return
     */
    public static int movingCountBFS(int m, int n, int k) {
        boolean[][] visited = new boolean[m][n];
        int res = 0;
        Queue<int[]> queue= new LinkedList<int[]>();
        queue.add(new int[] { 0, 0, 0, 0 });
        while(queue.size() > 0) {
            int[] x = queue.poll();
            int i = x[0], j = x[1], si = x[2], sj = x[3];
            if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;
            visited[i][j] = true;
            res ++;
            queue.add(new int[] { i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj });
            queue.add(new int[] { i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8 });
        }
        return res;
    }

    /**
     * DFS
     * 利用辅助数组,标记自己走过的位置
     * @param m
     * @param n
     * @param k
     * @return
     */
    public static int movingCountDFS(int m, int n, int k) {
        boolean[][] visited = new boolean[m][n];
        return dfs(0, 0, m, n, k, visited);
    }

    public static int dfs(int i,int j,int m,int n,int k,boolean[][] visited) {
        if (i < 0 || i >= m || j < 0 || j >= n ||
                (i/10 + i%10 + j/10 + j%10) > k ||
                visited[i][j]) {
            return 0;
        }
        visited[i][j] = true;
        return dfs(i + 1, j, m, n, k, visited)
                + dfs(i - 1, j, m, n, k, visited)
                + dfs(i, j + 1, m, n, k, visited)
                + dfs(i, j - 1, m, n, k, visited) + 1;

    }



}

4.总结
  • 参考题解
  • 读题,提取信息,遍历题库,找到类型,找到相应的解决方法。
  • BFS—>借助队列
  • DFS—>需要标记走过的路
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值