【刷题之路Ⅱ】百度面试题——迷宫问题

news2025/4/17 4:45:24

【刷题之路Ⅱ】百度面试题——迷宫问题

  • 一、题目描述
  • 二、解题
    • 1、方法1——暴力递归
      • 1.1、思路分析
      • 1.2、先将栈实现一下
      • 1.3、代码实现

一、题目描述

原题连接: 迷宫问题
题目描述:
定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。

数据范围:
2≤n,m≤10 , 输入的内容只包含 0≤val≤1

输入描述:

输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输出描述:
左上角到右下角的最短路径,格式如样例所示。

示例1

输入
5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出
(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)

示例2

输入
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 1
0 1 1 1 0
0 0 0 0 0
输出
(0,0)
(1,0)
(2,0)
(3,0)
(4,0)
(4,1)
(4,2)
(4,3)
(4,4)

说明
注意:不能斜着走!!

二、解题

1、方法1——暴力递归

解决这道题我采用的是比较暴力的方法,就是将所有的路都走一遍,因为题目只要求求出一条通路,所以只需要直到一条通路就可以结束了。

1.1、思路分析

那我们要怎样设计递归算法呢?
因为题目是要求我们将路径的坐标依次打印出来,所以很容易想到的就是将走过的路径的坐标依次压入栈中,例如:
在这里插入图片描述
只不过最后找到通路后的打印要想将栈中的元素逆置过来再打印。

如果走到某个坐标发现走到了死胡同(上下左右四个方向都走不通),那我们就将当前坐标弹出栈中,返回到上一个坐标继续判断有没有通路。
而为了避免“走回头路”而发生的死递归问题,我们需要将访问过的Maze的坐标的值改成2(其实改成任何数都可以,只要不要改成0就可以):
在这里插入图片描述
然后因为我们要压入栈中的是坐标,所以我们可以定义一个结构体pos,来保存Maze中每个元素对应的横坐标与纵坐标:

typedef struct position {
    int row;
    int col;
} pos;

然后我们就将栈的存储类型改成pos即可。

那我们主要的思路有了,那我们应该怎样设计算法呢?
其实我们主要要实现的只有一个函数——找通路的函数GetPath。
我们在GetPath函数里递归调用上下左右四个方向的找通路,如果当前被调用的坐标等于出口坐标就可以返回,而主要上下左右有任何一个方向的递归调用找到了通路就可以返回(同时最重要的是要先判断坐标的有效性)。

接下来还是看具体的代码实现吧:

1.2、先将栈实现一下

没办法,我用的是C语言,所以还是先要自己造轮子,这其实就只是个CV工程而已:

// 定义一个坐标结构体
typedef struct position {
    int row;
    int col;
} pos;
// 先要将栈实现一下
// 重定义数据类型
typedef pos DataType;

// 定义栈结构
typedef struct stack {
    DataType* data;
    int top;
    int capacity;
} Stack;

// 栈的初始化
void StackInit(Stack* ps);

// 压栈
void StackPush(Stack* ps, DataType x);
// 弹栈
void StackPop(Stack* ps);
// 返回栈顶数据
DataType StackTop(Stack* ps);
// 返回栈的数据个数
int StackSize(Stack* ps);
// 判断栈是否为空
bool StackEmpty(Stack* ps);
// 栈的销毁
void DestroyStack(Stack* ps);

// 栈的初始化
void StackInit(Stack* ps) {
    assert(ps);
    ps->data = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

// 压栈
void StackPush(Stack* ps, DataType x) {
    assert(ps);
    // 检查是否需要增容
    if (ps->top == ps->capacity) {
        int newCapacity = ps->capacity == 0 ? 10 : ps->capacity * 2;
        DataType* temp = (DataType*)realloc(ps->data, newCapacity * sizeof(DataType));
        if (NULL == temp) {
            perror("ralloc fail!\n");
            exit(-1);
        }
        ps->data = temp;
        ps->capacity = newCapacity;
    }
    ps->data[ps->top] = x;
    ps->top++;
}

// 弹栈
void StackPop(Stack* ps) {
    assert(ps);
    assert(ps->top > 0);
    ps->top--;
}

// 返回栈顶数据
DataType StackTop(Stack* ps) {
    assert(ps);
    assert(!StackEmpty(ps));
    return ps->data[ps->top - 1];
}

// 返回栈的数据个数
int StackSize(Stack* ps) {
    assert(ps);
    assert(ps->top >= 0);
    return ps->top;
}

// 判断栈是否为空
bool StackEmpty(Stack* ps) {
    assert(ps);
    return ps->top == 0;
}

// 栈的销毁
void DestroyStack(Stack* ps) {
    assert(ps);
    free(ps->data);
    ps->data = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

1.3、代码实现

因为我们要在多个函数之中使用同一个栈,而每次传参都传一个栈的话就有点太麻烦了。所以我们可以直接将栈定义成全局的。
注意 :因为这里是io型的oj题,所以我们没必要在main函数中最开始就将栈初始化,如果是接口型的oj题,就一定要在main函数中先将栈初始化,不然最多只能过一个测试用例。

// 先定义一个全局栈
Stack pathStack;

main函数:

int main() {
    int Row = 0;
    int Col = 0;
    while (scanf("%d %d", &Row, &Col) != EOF) {
        int** path = (int**)malloc(Row * sizeof(int*));
        if (NULL == path) {
            perror("malloc fail!\n");
            exit(-1);
        }
        int i = 0;
        for (i = 0; i < Row; i++) {
            path[i] = (int*)malloc(Col * sizeof(int));
            if (NULL == path[i]) {
                perror("malloc fail!\n");
                exit(-1);
            }
        }
        int j = 0;
        for (i = 0; i < Row; i++) {
            for (j = 0; j < Col; j++) {
                scanf("%d", &path[i][j]);
            }
        }
        pos entry = { 0 , 0 }; // 入口
        if (GetPath(path, Row, Col, entry)) {
            printPath();
        }
        else {
            printf("没有找到通路\n");
        }
    }
    DestroyStack(&pathStack);
}

找通路函数GetPath:

bool GetPath(int** path, int row, int col, pos cur) {
    assert(path);
    StackPush(&pathStack, cur);
    if (cur.row == row - 1 && cur.col == col - 1) {
        return true;
    }
    path[cur.row][cur.col] = 2;

    // 判断当前坐标的上下左右四个方向是否能走

    pos next = { 0, 0 };

    next = cur;
    // 上
    next.row += 1;
    if (isPass(path, row, col, next)) {
        if (GetPath(path, row, col, next)) {
            return true;
        }
    }

    next = cur;
    // 下
    next.row -= 1;
    if (isPass(path, row, col, next)) {
        if (GetPath(path, row, col, next)) {
            return true;
        }
    }

    next = cur;
    // 左
    next.col -= 1;
    if (isPass(path, row, col, next)) {
        if (GetPath(path, row, col, next)) {
            return true;
        }
    }

    next = cur;
    // 右
    next.col += 1;
    if (isPass(path, row, col, next)) {
        if (GetPath(path, row, col, next)) {
            return true;
        }
    }

    StackPop(&pathStack);
    return false;
}

判断坐标是否能走:

bool isPass(int** path, int row, int col, pos cur) {
    assert(path);
    if ((cur.row >= 0 && cur.row < row)
        && (cur.col >= 0 && cur.col < col)
        && path[cur.row][cur.col] == 0) {
        return true;
    }
    return false;
}

打印通路:

void printPath() {
    Stack RPathStack;
    StackInit(&RPathStack);

    // 将PathStack栈中的数据全都压入RPathStack栈中
    while (!StackEmpty(&pathStack)) {
        StackPush(&RPathStack, StackTop(&pathStack));
        StackPop(&pathStack);
    }

    pos cur = { 0, 0 };
    // 再将RPathStack栈中的数据取出来打印
    while (!StackEmpty(&RPathStack)) {
        cur = StackTop(&RPathStack);
        StackPop(&RPathStack);
        printf("(%d,%d)\n", cur.row, cur.col);
    }
    DestroyStack(&RPathStack);
}```



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自学网络安全(黑客),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而…

Fiddler抓包工具之fiddler设置抓HTTPS的请求证书安装

设置抓HTTPS的请求包 基础配置&#xff1a; 路径&#xff1a;启动Fiddler 》Tools》Options》HTTPS 注意&#xff1a;Option更改完配置需重启Fiddler才能生效 选中"Decrpt HTTPS traffic", Fiddler就可以截获HTTPS请求&#xff0c;如果是第一次会弹出证书安装提…

车载软件架构 —— 功能安全与基础软件

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 在最艰难的时候&#xff0c;自己就别去幻想太远的将来&#xff0c;只要鼓励自己过好今天就行了&#xff01; 这世…

node.js 学习 -- koa

一、搭建项目 1. 安装 Koa 框架 yarn add koa2. 引入 const Koa require("koa"); const app new Koa();3. 配置中间件 // ctx 所有http的上下文 // 配置中间件 app.use((ctx, next) > {ctx.body "hello api"; });4. 监听端口 app.listen(3000, …

TPO69 01|Why Snakes Have Forked Tongues|阅读真题精读|10:40-11:40+15:30-16:57

Why Snakes Have Forked Tongues 5/10 目录 Why Snakes Have Forked Tongues P1 P1生词 P1段落大意 无题目 P2 P2生词 P2段落大意 P2题目 【1】词汇题 secreteproduce ✅ 【2】事实信息题|考频高|难度高|定位错误​ P34​ P34生词 P34段落大意 P34题目 【3】词汇题 simultaneo…

入理解深度学习——正则化(Regularization):提前终止(Early Stopping)

分类目录&#xff1a;《深入理解深度学习》总目录 当训练有足够的表示能力甚至会过拟合的大模型时&#xff0c;我们经常观察到&#xff0c;训练误差会随着时间的推移逐渐降低但验证集的误差会再次上升。下图是这些现象的一个例子&#xff0c;这种现象几乎一定会出现。 这意味…

RT-Thread 学习笔记:memheap 死机问题的分析与解决

验证环境 NUCLEO-L476RG 开发板&#xff0c;板载 STM32L476RGT6&#xff08;96K SARM1 32K SRAM2&#xff09; Win10 64 位 Keil MDK 5.36 RT-Thread 5.0.1 版本&#xff08;2023-05-28 master 主线&#xff09; bsp : bsp\stm32\stm32l476-st-nucleo 功能描述 最近在研…

机器学习-线性代数-矩阵与空间映射

矩阵 文章目录 矩阵直观理解特殊矩阵矩阵的基本运算矩阵( A A A)乘向量( x x x)的本质&#xff1a;改变空间位置矩阵&#xff1a;空间映射关系矮胖矩阵对空间的降维压缩高瘦矩阵无法覆盖目标空间方阵映射矩阵的秩 直观理解 一个 m n m \times n mn的大小矩阵&#xff0c;直观…

fastjson与lombok一起用出现序列化问题

文章内部信息已脱敏。 有一次在测试环境调用网易电子签章平台的接口&#xff0c;用来生成印章图片。 首先用postman去测试接口&#xff0c;除了必传的固定请求头&#xff0c;请求体参数如下&#xff1a; {"userId": "***********","templateType&qu…

数据在内存中是如何存储的?(上)

C语言进阶——数据在内存中是如何存储的&#xff1f; 一. 整型数据的二进制表示二.数据类型详细介绍1.1 类型的基本归类1.2认识有无符号的区别&#xff08; signed 和 unsigned &#xff09;1.3代码理解一&#xff1a;1.4代码二理解&#xff1a;1.5代码三理解&#xff1a;1.6代…

【P40】JMeter 录制控制器(Recording Controller)

文章目录 一、录制控制器&#xff08;Recording Controller&#xff09;二、准备工作三、测试计划设计 一、录制控制器&#xff08;Recording Controller&#xff09; 可以理解为一个占位符&#xff0c;用来告诉代理服务器将脚本录制到何处&#xff0c;本身无任何逻辑作用&…

AI时代来临,新时代程序员如何紧追时代的风口浪尖?

文章目录 背景AI时代的背景和机遇抓住AI时代的机遇新时代程序员的技能和素质实践建议和资源总结 背景 在这个快速发展的AI时代&#xff0c;程序员们正置身于科技革新的前沿。随着人工智能技术的蓬勃发展和广泛应用&#xff0c;程序员的作用变得愈发重要和关键。他们不再是简单…

Doris之rollup上卷及物化视图

Rollup上卷 通过建表语句创建出来的表称为 Base 表&#xff08;Base Table,基表&#xff09; 在 Base 表之上&#xff0c;我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的&#xff0c;并且在物理上是独立存储的。 Rollup表的好处&#xff1a; 和基表…

如何在华为OD机试中获得满分?Java实现【最长的连续子序列】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

如何在华为OD机试中获得满分?Java实现【滑动窗口】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

软件测试理论----接口测试中restful接口状态码规范

一、restful接口状态码总体分类 类别描述1xx&#xff1a;信息通信传输协议信息2xx&#xff1a;成功表示客户端的请求已成功接受3xx&#xff1a;重定向表示客户端必须执行一些其他操作才能完成其请求4xx&#xff1a;客户端错误此类错误状态码指向客户端5xx&#xff1a;服务器错…

在SPSS Statistics中使用R(插件)

date: 2018-10-30 09:26:33 在SPSS中使用R&#xff08;插件&#xff09; 谷歌或者百度“SPSS中调用R”, 最详细也是最靠谱的就是IBM SPSS社区的这两篇文章: https://www.ibm.com/developerworks/cn/data/library/ba/ba-1401spss-r/https://www.ibm.com/developerworks/cn/ana…

基于Open3D的点云处理6-点云去噪

当我们从扫描设备获取点云数据时&#xff0c;数据会包含噪声和伪影&#xff0c;点云噪声特性包括不真实的点、孤立点、不规则&#xff0c;基于噪声特性对器进行去除&#xff1b; 统计滤波 Statistical Outlier Removal&#xff08;SOR&#xff09;&#xff08;去除离群点&…

【JVM】13. 垃圾回收器

文章目录 13.1. GC分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估GC的性能指标吞吐量暂停时间吞吐量 vs 暂停时间 13.2. 不同的垃圾回收器概述13.2.1. 垃圾回收器发展史13.2.2. 7种经典的垃圾收集器13.2.3. 7款经典收集器与垃圾分代之间的关系13.2.4…

前端自动化测试 —— Jest 测试框架应用

目录​​​​​​​ 什么是自动化测试 为什么要用前端自动化测试 前端自动化分类和思想 单元测试 集成测试 TDD 测试驱动开发&#xff08;Test Driven Development&#xff09; BDD 行为驱动开发&#xff08;Behavior Driven Development&#xff09; 如何自己写非框架…