zoukankan      html  css  js  c++  java
  • 剑指offer13

    地上有一个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。请问该机器人能够到达多少个格子?

    分析:该题分析是一个矩阵的遍历过程,但是不可以直接使用两个嵌套for循环来遍历,求取满足条件的坐标点个数,因为存在着某些点满足条件,但是其周围的点都是不可达的,那么该点还是不可达。所以判断点是否可达应该一个点一个点的来看,我想到的是使用回溯法的方法,用stack来记录当前的坐标点,栈不为空就pop栈顶坐标,分析该坐标是否可达,之后分别分析将该点下移和右移是否满足条件(为啥只需要下移和右移后面分析,这个问题是我做这题的时候一个很难想的问题),满足则push入栈,否则跳过。其实我觉得也可以使用队列,也是可以的。

    问题:为什么只需要看向下移动和向右移动,而不需要看向上移动和向左移动?题目中的数位之和记为f()

    若相邻的三个数分别为x-1,x,x+1,一定只会x-1满足条件,其他x,x+1满足不满足均有可能,一定不会x-1不满足,x,x+1满足条件
    当x+1不发生十位上的进位时,则f(x-1)<f(x)<f(x+1),当x-1不满足的时候,x,x+1肯定也不满足
    当x+1发生个位上的进位时,f(x+1)+8 = f(x),f(x-1)+1 = f(x),所以可以发现解的情况应该是如上图所示的,从坐标领零点开始,下面一行的解总是比上一行的少一个,而且第一行的解也会在个位发生进位的时候发生突变,这样原本本来一直不满足的点,经过进位可能就满足了,但是尽管这样解也同样是一个上图的三角形,最好的情况也是第一行的两个三角形连起来,但这样同样只需要向下,向右遍历即可,若两个三角形的解不相连更不用说,我在做这题的时候这个地方困扰了我好久,开始一直想着应该四个方向,但是这样就会发生死循环,经过回过头的分析,以后做题想不通的要学会手动推导一下,不要仅仅画一些简单的示意图。

    算法代码:

     1 class Solution {
     2 
     3     public int movingCount(int m,int n,int k){
     4         // 状态矩阵用来记录某一个点是否已经检测可达,可达标为1,默认为零,不可达为-1
     5         int[][] state = new int[m][n];
     6         int num = 0; // 记录可达的数量
     7 
     8         // 定义初始的坐标x,y变量
     9         int x=0,y=0;
    10         Stack<int[]> stack = new Stack();
    11         stack.push(new int[]{x,y});
    12 
    13         while(!stack.empty()){
    14             int[] temp = stack.pop();
    15             x = temp[0];y = temp[1];
    16             // 判断pop出的坐标是否符合,不符合就不用看向前后左右移动
    17             if(isOk(temp[0],temp[1],k)){
    18                 if(state[x][y] != 1) {num++; state[x][y] = 1;}
    19                 // 向下,如何合规就push
    20                 if(x+1<m&&isOk(x+1,y,k)&&state[x+1][y]==0) stack.push(new int[]{x+1,y});
    21 
    22                 // 向右,如果合规就push
    23                 if(y+1<n&&isOk(x,y+1,k)&&state[x][y+1]==0) stack.push(new int[]{x,y+1});
    24             }
    25         }
    26 
    27         return num;
    28     }
    29 
    30 
    31     // 判断(x,y)是否是合法的位置
    32     public static boolean isOk(int x,int y,int k){
    33         int sum = 0;
    34         while(x>=10){sum += x%10; x/=10;}
    35         while(y>=10){sum += y%10; y/=10;}
    36 
    37         return sum+x+y<=k?true:false;
    38     }
    39 }
    知之为知之,不知为不知
  • 相关阅读:
    浏览器图片渲染优化教程
    C#把 DataTable转换为Model实体
    .NET静态变量与静态方法并发的问题
    三种方法查看MySQL数据库的版本
    Mysql 存储引擎 InnoDB与Myisam的主要区别
    dotnet core 出现Can not find runtime target for framework '.NETCoreApp,Version=v1.6' 的解决办法
    细说 C# 中的 IEnumerable和IEnumerator接口
    ASP.NET CORE dotnet run 命令使用debug方式运行
    安装了插件情况下 强制开启火狐浏览器的多进程功能
    JSON 字符串中的中括号和大括号区别详解
  • 原文地址:https://www.cnblogs.com/bevishe/p/12416807.html
Copyright © 2011-2022 走看看