• 【限时免费】20天拿下华为OD笔试之 【回溯】2023B-找到它【欧弟算法】全网注释最详细分类最全的华为OD真题题解


    题目描述与示例

    题目描述

    找到它是个小游戏,你需要在一个矩阵中找到给定的单词 假设给定单词HELLOWORLD,在矩阵中只要能找HELLOWORLD就算通过 注意区分英文字母大小写,并且你只能上下左右行走,不能走回头路

    输入描述

    输入第一行包含两个整数N M (0 < N, M < 21) 分别表示NM列的矩阵 第二行是长度不超过100的单词W 在整个矩阵中给定单词W只会出现一次 从第3行到第N+2是只包含大小写英文字母的长度为M的字符串矩阵

    输出描述

    如果能在矩阵中连成给定的单词,则输出给定单词首字母在矩阵中的位置为第几行第几列 否则输出 NO

    示例一

    输入

    5 5
    HELLOWORLD
    CPUCY
    EKLQH
    CHELL
    LROWO
    DGRBC
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出

    3 2
    
    • 1

    示例二

    输入

    5 5
    Helloworld
    CPUCh
    wolle
    orldO
    EKLQo
    PGRBC
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出

    NO
    
    • 1

    解题思路

    注意,本题和LeetCode79. 单词搜索几乎完全一致,唯一的区别在于前者只要求判断是否能够找到该单词,本题还需要输出起始位置。

    代码

    Python

    # 题目:2023B-找到它
    # 分值:200
    # 作者:许老师-闭着眼睛学数理化
    # 算法:回溯
    # 代码看不懂的地方,请直接在群上提问
    
    
    # 全局的方向数组,表示上下左右移动四个方向
    DIRECTIONS = [(0,1), (1,0), (-1,0), (0,-1)]
    
    # 构建回溯函数,各个参数的含义为
    # grid:         原二维矩阵
    # N,M:          原二维矩阵的行数、列数
    # check_list:   大小和grid一样的检查列表,用于判断某个点是否已经检查过
    # x,y:          当前在grid中的点的坐标
    # word:         待搜索的单词
    # word_idx:     待搜索的单词此时遍历到的索引位置
    def backtracking(grid, N, M, check_list, x, y, word, word_idx):
        # 声明全局变量isFind
        global isFind
        # 若此时word_idx等于word的长度-1
        # 说明word中的所有字母都在grid中找到了
        # 修改isFind为True,同时终止递归
        if word_idx == len(word) - 1:
            isFind = True
            return
        # 遍历四个方向,获得点(x,y)的近邻点(nx,ny)
        for dx, dy in DIRECTIONS:
            nx, ny = x+dx, y+dy
            # (nx,ny)必须满足以下三个条件,才可以继续进行回溯函数的递归调用
            # 1. 不越界;2. 尚未检查过;
            # 3.在grid中的值grid[nx][ny]为word的下一个字符word[word_idx+1]
            if 0 <= nx < len(grid) and 0 <= ny < len(grid[0]) and check_list[nx][ny] == False and grid[nx][ny] == word[word_idx+1]:
                # 状态更新,将点(nx,ny)在check_list中的状态更新为True
                check_list[nx][ny] = True
                # 回溯,将点(nx,ny)传入回溯函数中,注意此时word_idx需要+1
                backtracking(grid, N, M, check_list, nx, ny, word, word_idx+1)
                # 回滚,将点(nx,ny)在check_list中的状态重新修改回False
                check_list[nx][ny] = False
    
    
    # 输入行数和列数
    N, M = map(int, input().split())
    # 输入待查找的单词
    word = input()
    # 构建二维网格
    grid = list()
    for _ in range(N):
        grid.append(input())
    
    # 构建全局变量isFind,初始化为False
    isFind = False
    
    # 双重遍历整个二维网格grid
    for i in range(N):
        for j in range(M):
            # 找到点(i,j)等于word的第一个字母
            # 则点(i,j)可以作为递归的起始位置
            if grid[i][j] == word[0]:
                # 构建大小和grid一样的检查数组check_list
                # 用于避免出现重复检查的情况
                check_list = [[False] * M for _ in range(N)]
                # 将点(i,j)在check_list中设置为已检查过
                check_list[i][j] = True
                # 回溯函数递归入口
                backtracking(grid, N, M, check_list, i, j, word, 0)
                # 如果在回溯中,全局变量isFind被改为True,说明找到了单词
                if isFind:
                    # 输出行数和列数,注意在问题中行数和列数是从1开始计数的
                    # 所以存在一个+1操作
                    print("{} {}".format(i+1, j+1))
                    # 同时可以直接退出循环
                    break
        if isFind:
            break
    
    if not isFind:
        print("NO")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    Java

    import java.util.Scanner;
    
    public class Main {
        // Global directions array to represent four directions: up, down, left, right
        private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
        private static boolean isFind = false;
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int N = scanner.nextInt();
            int M = scanner.nextInt();
            scanner.nextLine(); // Consume newline
            String word = scanner.nextLine();
    
            char[][] grid = new char[N][M];
            for (int i = 0; i < N; i++) {
                String row = scanner.nextLine();
                for (int j = 0; j < M; j++) {
                    grid[i][j] = row.charAt(j);
                }
            }
    
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (grid[i][j] == word.charAt(0)) {
                        boolean[][] checkList = new boolean[N][M];
                        checkList[i][j] = true;
                        backtracking(grid, N, M, checkList, i, j, word, 0);
                        if (isFind) {
                            System.out.println((i + 1) + " " + (j + 1));
                            return;
                        }
                    }
                }
            }
    
            if (!isFind) {
                System.out.println("NO");
            }
        }
    
        private static void backtracking(char[][] grid, int N, int M, boolean[][] checkList, int x, int y, String word, int wordIdx) {
            if (wordIdx == word.length() - 1) {
                isFind = true;
                return;
            }
    
            for (int[] dir : DIRECTIONS) {
                int nx = x + dir[0];
                int ny = y + dir[1];
    
                if (nx >= 0 && nx < N && ny >= 0 && ny < M && !checkList[nx][ny] && grid[nx][ny] == word.charAt(wordIdx + 1)) {
                    checkList[nx][ny] = true;
                    backtracking(grid, N, M, checkList, nx, ny, word, wordIdx + 1);
                    checkList[nx][ny] = false;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    C++

    #include 
    #include 
    
    using namespace std;
    
    // Global directions array to represent four directions: up, down, left, right
    const vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
    bool isFind = false;
    
    // Backtracking function
    void backtracking(vector<vector<char>>& grid, int N, int M, vector<vector<bool>>& checkList, int x, int y, string& word, int wordIdx) {
        if (wordIdx == word.length() - 1) {
            isFind = true;
            return;
        }
    
        for (const auto& dir : DIRECTIONS) {
            int nx = x + dir.first;
            int ny = y + dir.second;
    
            if (nx >= 0 && nx < N && ny >= 0 && ny < M && !checkList[nx][ny] && grid[nx][ny] == word[wordIdx + 1]) {
                checkList[nx][ny] = true;
                backtracking(grid, N, M, checkList, nx, ny, word, wordIdx + 1);
                checkList[nx][ny] = false;
            }
        }
    }
    
    int main() {
        int N, M;
        cin >> N >> M;
        string word;
        cin >> word;
    
        vector<vector<char>> grid(N, vector<char>(M));
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cin >> grid[i][j];
            }
        }
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (grid[i][j] == word[0]) {
                    vector<vector<bool>> checkList(N, vector<bool>(M, false));
                    checkList[i][j] = true;
                    backtracking(grid, N, M, checkList, i, j, word, 0);
                    if (isFind) {
                        cout << i + 1 << " " << j + 1 << endl;
                        return 0;
                    }
                }
            }
        }
    
        if (!isFind) {
            cout << "NO" << endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    时空复杂度

    时间复杂度:O(NM3^L)。其中L为单词word的长度,这是一个比较宽松的上界,回溯过程中每一个点都最多有三个分支可以进入。

    空间复杂度:O(NM)check_list所占空间。


    华为OD算法/大厂面试高频题算法练习冲刺训练

    • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

    • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

    • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

    • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

    • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

    • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

    • 绿色聊天软件戳 od1336了解更多

  • 相关阅读:
    这就是!Python的魅力!
    【附源码】Python计算机毕业设计数据结构知识点渐进学习网站
    Databend v0.8 新版本上线!
    尤雨溪对 2022 Web前端生态趋势是这样看的
    29、CSS进阶——美化表单元素
    MySQL索引机制(详细+原理+解析)
    初识Pytest自动化测试框架,我彻底懂了
    【计算机网络】TCP协议
    Apache JMeter 和 Locust的对比
    视频编解码 — 带宽预测
  • 原文地址:https://blog.csdn.net/weixin_48157259/article/details/134438372