2021-11-08 剑指offer--回溯

JZ12 矩阵中的路径

题目地址
描述
请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
[ a b c e s f c s a d e e ] \begin{bmatrix} a & b &c & e\\ s & f &c&s\\ a&d&e&e\end{bmatrix} \quad asabfdcceese
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

数据范围:,
0 ≤ n , m ≤ 20,1 ≤ len ≤ 25

进阶:时间复杂度0(n^2), 空间复杂度0(n^2)

示例1

输入:
[[a,b,c,e],[s,f,c,s],[a,d,e,e]],"abcced"
返回值:
true

示例2

输入:
[[a,b,c,e],[s,f,c,s],[a,d,e,e]],"abcb"
返回值:
false

备注
0 <= matrix.length <= 200
0 <= matrix[i].length <= 200

代码

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param matrix char字符型二维数组 
     * @param word string字符串 
     * @return bool布尔型
     */
    public boolean hasPath (char[][] matrix, String word) {
        // write code here
        if(matrix==null||matrix[0]==null||word==null) return false;
        char[] strs=word.toCharArray();
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[0].length;j++){
                if(matrix[i][j]==strs[0]){
                    boolean[][]visit=new boolean[matrix.length][matrix[0].length];
                    visit[i][j]=true;
                    if(dfs(matrix,strs,1,i,j,visit)){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    /*
    *matrix:字符数组
    *word:要匹配的单词串
    *index:遍历到第index个单词
    *(i,j)matrix数组下标
    *visit[][]:判断某个单词是否被问过
	*/
    public boolean dfs(char[][] matrix,char[] word,int index,int i,int j,boolean[][] visit){
    	//待匹配字符串遍历完
        if(index>=word.length){
            return true;
        }
        //四个方向可以进行遍历
        int[][] f={{1,-1,0,0},{0,0,1,-1}};
        boolean find=false;//判断是否找到匹配串
        for(int k=0;k<4;k++){
            //越界
            if(i+f[0][k]<0 || i+f[0][k]>=matrix.length || j+f[1][k]<0 || j+f[1][k]>=matrix[0].length){
                continue;
            }
            //已经访问过
            if(visit[i+f[0][k]][j+f[1][k]]) continue;
            //只有要遍历的字符值 = word中的值时才遍历
            if(matrix[i+f[0][k]][j+f[1][k]]==word[index]){
                visit[i+f[0][k]][j+f[1][k]]=true;
                find=find||dfs(matrix,word,index+1,i+f[0][k],j+f[1][k],visit);
                visit[i+f[0][k]][j+f[1][k]]=false;
            }
        }
        return find;
    }
}

JZ13 机器人的运动范围

题目地址
描述
地上有一个 rows 行和 cols 列的方格。坐标从 [0,0] 到 [rows-1,cols-1] 。一个机器人从坐标 [0,0] 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 threshold 的格子。 例如,当 threshold 为 18 时,机器人能够进入方格 [35,37] ,因为 3+5+3+7 = 18。但是,它不能进入方格 [35,38] ,因为 3+5+3+8 = 19 。请问该机器人能够达到多少个格子?

数据范围: 0 ≤ threshold ≤ 15,1≤ cols,rows ≤ 100

进阶:空间复杂度0(nm) ,时间复杂度0(nm)

示例1

输入:
1,2,3
返回值:
3

示例2

输入:
0,1,3
返回值:
1

示例3

输入:
10,1,100
返回值:
29
说明:
[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[0,10],[0,11],[0,12],[0,13],[0,14],[0,15],[0,16],[0,17],[0,18],[0,19],[0,20],[0,21],[0,22],[0,23],[0,24],[0,25],[0,26],[0,27],[0,28] 这29种,后面的[0,29],[0,30]以及[0,31]等等是无法到达的   

示例4

输入:
5,10,10
返回值:
21

代码

public class Solution {
    public int movingCount(int threshold, int rows, int cols) {
        boolean[][]visit=new boolean[rows][cols];
        int count= dfs(threshold,0,0,rows,cols,visit);
        for(int i=0;i<visit.length;i++){
            for(int j=0;j<visit[0].length;j++){
                System.out.print(i+","+j+"("+visit[i][j]+") ");
            }
            System.out.println();
        }
        return count;
    }
    /*
    *(i,j)是坐标,表示到达了那个位置
    *rows,cols表示位置矩阵的行和列
    *visit[][]判断某个位置是否被访问过
    */
    public int dfs(int threshold,int i,int j,int rows,int cols,boolean[][] visit){
        visit[i][j]=true;
        int count=1;
        int[][] f={{1,-1,0,0},{0,0,1,-1}};
        for(int k=0;k<4;k++){
            if(i+f[0][k]<0 || i+f[0][k]>=rows || j+f[1][k]<0 || j+f[1][k]>=cols){
                continue;
            }
            if(visit[i+f[0][k]][j+f[1][k]]) continue;
            if(!isValid(i+f[0][k],j+f[1][k],threshold)) continue;
            visit[i+f[0][k]][j+f[1][k]]=true;
            count+=dfs(threshold,i+f[0][k],j+f[1][k],rows,cols,visit);
        }
        return count;
    }
    //判断坐标(i,j)是否是有效的,即坐标i,j数位和小于等于threshold
    public boolean isValid(int i,int j,int threshold){
        int count=0;
        while(i>0){
            count+=i%10;
            i/=10;
        }
        while(j>0){
            count+=j%10;
            j/=10;
        }
        return count<=threshold;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值