C++结合Lambda表达式在函数内部实现递归

news2025/1/15 17:43:40

529. 扫雷游戏

已解答

中等

相关标签

相关企业

让我们一起来玩扫雷游戏!

给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中:

  • 'M' 代表一个 未挖出的 地雷,
  • 'E' 代表一个 未挖出的 空方块,
  • 'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的 已挖出的 空白方块,
  • 数字'1' 到 '8')表示有多少地雷与这块 已挖出的 方块相邻,
  • 'X' 则表示一个 已挖出的 地雷。

给你一个整数数组 click ,其中 click = [clickr, clickc] 表示在所有 未挖出的 方块('M' 或者 'E')中的下一个点击位置(clickr 是行下标,clickc 是列下标)。

根据以下规则,返回相应位置被点击后对应的盘面:

  1. 如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X' 。
  2. 如果一个 没有相邻地雷 的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的 未挖出 方块都应该被递归地揭露。
  3. 如果一个 至少与一个地雷相邻 的空方块('E')被挖出,修改它为数字('1' 到 '8' ),表示相邻地雷的数量。
  4. 如果在此次点击中,若无更多方块可被揭露,则返回盘面。

示例 1:

输入:board = [["E","E","E","E","E"],["E","E","M","E","E"],["E","E","E","E","E"],["E","E","E","E","E"]], click = [3,0]
输出:[["B","1","E","1","B"],["B","1","M","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]]

示例 2:

输入:board = [["B","1","E","1","B"],["B","1","M","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]], click = [1,2]
输出:[["B","1","E","1","B"],["B","1","X","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 50
  • board[i][j] 为 'M''E''B' 或数字 '1' 到 '8' 中的一个
  • click.length == 2
  • 0 <= clickr < m
  • 0 <= clickc < n
  • board[clickr][clickc] 为 'M' 或 'E'

这是一道leetcode上面的题目,题目本身不难,只需要改变一次状态就行了。改变状态中需要确定点击的是什么内容,如果是空白则需要递归找到所有的空白。

先用AI先了一个python版本:

class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]  # 相邻方向

        def count_mines(r, c):
            count = 0
            for dr, dc in directions:
                nr, nc = r + dr, c + dc
                if 0 <= nr < len(board) and 0 <= nc < len(board[0]) and board[nr][nc] == 'M':
                    count += 1
            return count

        def reveal(r, c):
            if board[r][c] == 'E':
                mines_count = count_mines(r, c)
                if mines_count == 0:
                    board[r][c] = 'B'
                    for dr, dc in directions:
                        nr, nc = r + dr, c + dc
                        if 0 <= nr < len(board) and 0 <= nc < len(board[0]):
                            reveal(nr, nc)
                else:
                    board[r][c] = str(mines_count)

        click_r, click_c = click
        if board[click_r][click_c] == 'M':
            board[click_r][click_c] = 'X'
        else:
            reveal(click_r, click_c)

        return board

 python果然更加现代,函数里面可以定义函数。想着将python改写为C++实现,C++虽然无法在函数内部实现函数,但是有lamda表达式,于是写出来下面的版本:

#include <vector>
#include <string>

using namespace std;

class Solution {
public:
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        int directions[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 相邻方向

        auto countMines = [&](int r, int c) -> int {
            int count = 0;
            for (auto& dir : directions) {
                int nr = r + dir[0], nc = c + dir[1];
                if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size() && board[nr][nc] == 'M') {
                    ++count;
                }
            }
            return count;
        };

        auto revealFunc = [&](int r, int c) {
            if (board[r][c] == 'E') {
                int minesCount = countMines(r, c);
                if (minesCount == 0) {
                    board[r][c] = 'B';
                    for (auto& dir : directions) {
                        int nr = r + dir[0], nc = c + dir[1];
                        if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size()) {
                            revealFunc(nr, nc);
                        }
                    }
                } else {
                    board[r][c] = '0' + minesCount;
                }
            }
        };

        int click_r = click[0], click_c = click[1];
        if (board[click_r][click_c] == 'M') {
            board[click_r][click_c] = 'X';
        } else {
            revealFunc(click_r, click_c);
        }

        return board;
    }
};

啊,编译报错了。

 error: variable 'revealFunc' declared with deduced type 'auto' cannot appear in its own initializer
   23 |                             revealFunc(nr, nc);
      |                             ^
1 error generated.
还是不行,不能递归调用。

在C++中,Lambda表达式不能直接递归调用自身,因为它的类型是在声明时确定的,而在递归调用时,Lambda表达式的类型还没有完全确定。
为了解决这个问题,你可以将Lambda表达式存储在一个std::function对象中,这样就可以在递归调用中使用它了。std::function是一个可以存储任何可调用对象的通用容器,只要其签名与std::function的模板参数匹配即可。

正确版本:

class Solution {
public:
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        int directions[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 相邻方向
        auto countMines = [&](int r, int c) -> int {
            int count = 0;
            for (auto& dir : directions) {
                int nr = r + dir[0], nc = c + dir[1];
                if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size() && board[nr][nc] == 'M') {
                    ++count;
                }
            }
            return count;
        };
        std::function<void(int, int)> revealFunc;
        revealFunc = [&](int r, int c) {
            if (board[r][c] == 'E') {
                int minesCount = countMines(r, c);
                if (minesCount == 0) {
                    board[r][c] = 'B';
                    for (auto& dir : directions) {
                        int nr = r + dir[0], nc = c + dir[1];
                        if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size()) {
                            revealFunc(nr, nc);
                        }
                    }
                } else {
                    board[r][c] = '0' + minesCount;
                }
            }
        };
        int click_r = click[0], click_c = click[1];
        if (board[click_r][click_c] == 'M') {
            board[click_r][click_c] = 'X';
        } else {
            revealFunc(click_r, click_c);
        }
        return board;
    }
};

执行用时分布

10ms

击败97.79%使用 C++ 的用户

消耗内存分布

15.11MB

击败15.20%使用 C++ 的用户

C++感觉需要重新学习了。。。

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

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

相关文章

01_02_mysql06_视图-存储过程-函数

视图 使用 视图一方面可以帮我们使用表的一部分而不是所有的表&#xff0c;另一方面也可以针对不同的用户制定不同的查询视图。比如&#xff0c;针对一个公司的销售人员&#xff0c;我们只想给他看部分数据&#xff0c;而某些特殊的数据&#xff0c;比如采购的价格&#xff0…

Rabbitmq入门与应用(三)-RabbitMQ开发流程

RabbitMQ开发流程 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>配置MQ 最简配置 spring:rabbitmq:host: mq的安装机器ipport: 5672username: ad…

手撕C语言习题

定义一个表示公交线路的结构体&#xff0c;要求有线路名称(例如 616)&#xff0c;起始站&#xff0c;终点站&#xff0c;里程等成员&#xff0c; 定义结构体数组&#xff0c;用来存储多条条公交线路信息&#xff0c;要求能够输出从指定起始站发车的所以公交线路信息。 2、定义…

C++11---(3)

目录 一、可变参数模板 1.1、可变参数模板的概念 1.2、可变参数模板的定义方式 1.3、如何获取可变参数 二、lambda表达式 2.1、Lamabda表达式定义 2.2、为什么有Lambda 2.3、Lambda表达式的用法 2.4、函数对象与lambda表达式 三、包装器 3.1、function 3.2、bind …

Web3探索加密世界:什么是空投?

随着加密货币行业的迅速发展&#xff0c;人们开始听说各种各样的术语&#xff0c;其中包括"空投"&#xff08;Airdrop&#xff09;。在这里&#xff0c;我们将深入探讨什么是空投&#xff0c;以及它在加密世界中扮演的角色。 什么是空投&#xff1f; 空投是指在加密…

Spring Boot应用集成Actuator组件以后怎么自定义端点暴露信息

一、 前言 在平时业务开发中&#xff0c;我们往往会在spring Boot项目中集成Actuator组件进行系统监控&#xff0c;虽然Actuator组件暴露的端点信息已经足够丰富了&#xff0c;但是特殊场景下&#xff0c;我们也需要自己暴露端点信息&#xff0c;此时应该怎么操作呢&#xff1…

4款AI写作软件推荐,让文章撰写更加轻松! #学习方法#知识分享

国外ChatGPT爆火&#xff0c;AI写作在国内也引起不小的瞩目&#xff0c;目前国内的AI写作工具少说也有几十上百个&#xff0c;要在这么多AI写作中找出适合自己的工具&#xff0c;一个一个尝试是不太现实的&#xff0c;所以今天就给大家推荐一些款AI写作工具。帮助你少走弯路&am…

请你设计一个抢手机F码的排队的场景,并且需要显示等待时间

package com.example.demo1.service.impl;import lombok.Data;import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Date;Data public class User {//用户idprivate Integer id;//姓名private String name;//插入的时间private LocalDate…

NestJS入门8:拦截器

前文参考&#xff1a; NestJS入门1&#xff1a;创建项目 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 NestJS入门4&#xff1a;MySQL typeorm 增删改查 NestJS入门5&#xff1a;加入Swagger NestJS入门6&#xff1a;日志中间件 Nes…

2023年便宜的云服务器分享:最低26元4核16G

2024年阿里云服务器租用价格表更新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服…

新手搭建服装小程序全攻略

随着互联网的快速发展&#xff0c;线上购物已经成为了人们日常生活中不可或缺的一部分。服装作为人们日常消费的重要品类&#xff0c;线上化趋势也日益明显。本文将详细介绍如何从零开始搭建一个服装小程序商城&#xff0c;从入门到精通的捷径&#xff0c;帮助你快速掌握小程序…

认识TypeScript 中的接口和类

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 接口 类 江城开朗的豌豆 在 TypeScript 中&…

Linux小程序--进度条

目录 1.知识补充 1.1回车和换行 1.2缓冲区 2.实现倒计时 3.实现进度条 1.知识补充 1.在制作小程序进度条之前&#xff0c;我们先了解一下&#xff0c;回车换行和行缓冲区的概念。 2.动态效果&#xff0c;在同一个位置刷新不同的图像&#xff0c;实现一个倒计时的效果。…

Stable Diffusion——基础模型、VAE、LORA、Embedding各个模型的介绍与使用方法

前言 Stable Diffusion&#xff08;稳定扩散&#xff09;是一种生成模型&#xff0c;基于扩散过程来生成高质量的图像。它通过一个渐进过程&#xff0c;从一个简单的噪声开始&#xff0c;逐步转变成目标图像&#xff0c;生成高保真度的图像。这个模型的基础版本是基于扩散过程…

剪辑视频调色软件有哪些 剪辑视频软件哪个最好 剪辑视频怎么学 剪辑视频的方法和步骤 会声会影2024 会声会影视频制作教程

看了很多调色教程&#xff0c;背了一堆调色参数&#xff0c;可最终还是调不出理想的效果。别再怀疑自己了&#xff0c;不是你的剪辑技术不行&#xff0c;而是剪辑软件没选对。只要掌握了最基本的调色原理&#xff0c;一款适合自己的视频剪辑软件是很容易出片的。 有关剪辑视频…

3个密码学相关的问题

一、离散对数问题&#xff08;Discrete Logarithm Problem, DLP&#xff09; 问题描述&#xff1a;给定 有限阿贝尓群 G中的2个元素a和b&#xff0c;找出最小的正整数x满足&#xff1a;b a ^^ x &#xff08;或者证明这样的x不存在&#xff09;。 二、阶数问题&#xff08;O…

自定义表单工作流的优势特点有啥?

低代码技术平台是提升办公效率的得力武器&#xff0c;在当今竞争激烈的社会中获得了很多中小企业的喜爱与支持。流辰信息是一家专业研发低代码技术平台的服务商&#xff0c;IBPS开发平台用于很多行业中&#xff0c;助力企业实现了办公流程化。自定义表单工作流的优势多、简单灵…

宝塔nginx配置SpringBoot服务集群代理

宝塔nginx配置SpringBoot服务集群代理 1、需求&#xff1a; 现有一个springboot服务需要部署成集群&#xff0c;通过nginx负载均衡进行访问&#xff0c;其中这个springboot服务内置了MQTT服务、HTTP服务、TCP服务。 MQTT服务开放了1889端口 HTTP服务开放了8891端口 HTTP服务开…

加固平板电脑在森林勘探上的应用|亿道三防onerugged

随着对森林资源的重视和需求的增长&#xff0c;森林勘探成为了一项重要的工作。在这个领域中&#xff0c;加固平板电脑的应用为森林勘探工作带来了显著的改善。 首先&#xff0c;三防平板电脑具备良好的耐用性和适应性&#xff0c;能够在恶劣的环境条件下稳定运行。在森林勘探…

LeetCode--代码详解 54.螺旋矩阵

54.螺旋矩阵 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff…