LeetCode:65.有效数字

news/2025/1/12 22:09:47/文章来源:https://www.cnblogs.com/KooTeam/p/18667461

LeetCode:65.有效数字

解题步骤构建一个表示状态的图。遍历字符串,并沿着图走,如果到了某个节点无路可走就返false。遍历结束,如走到3/5/6,就返回true,否则返回false。

extend 2 8 10 16进制

/*** 检查一个字符串是否可以表示为一个有效的数字* @param {string} s - 待检查的字符串* @returns {boolean} - 如果字符串是有效的数字表示,则返回true;否则返回false*/
var isNumber = function(s) {// 状态转换图,定义了字符串中每个字符类型在不同状态下如何转换状态const graph = {0: {'blank': 0, 'sign': 1, '.': 2, 'digit': 6},1: {'digit': 6, '.': 2},2: {'digit': 3},3: {'digit': 3, 'e': 4},4: {'digit': 5, 'sign': 7},5: {'digit': 5},6: {'digit': 6, '.': 3, 'e': 4},7: {'digit': 5}};// 初始化状态为0let state = 0;// 遍历字符串中的每个字符,去除首尾空格for (let c of s.trim()) {// 将字符分类为digit、blank、.、e、signif (c >= '0' && c <= '9') {c = 'digit';} else if (c === ' ') {c = 'blank';} else if (c === '.') {c = '.';} else if (c === 'e' || c === 'E') {c = 'e';} else if (c === '+' || c === '-') {c = 'sign';}// 根据当前状态和字符类型转换到下一个状态state = graph[state][c];// 如果转换结果为undefined,说明字符串不是有效的数字表示if (state === undefined) {return false;}}// 如果最终状态是3、5或6,则字符串是有效的数字表示return state === 3 || state === 5 || state === 6;
};// 示例:检查字符串"1E9"是否是有效的数字表示
console.log(isNumber("1E9"));

代码功能详细解释

这段 JavaScript 代码的功能是判断给定的字符串是否表示一个有效的数字。它使用有限状态机(FSM)来处理字符串中的每个字符,并根据预定义的状态转换规则进行状态切换。具体步骤如下:

  1. 初始化状态机

    • 定义了一个 graph 对象,表示不同状态之间的转换规则。
    • 每个状态对应一个对象,键为字符类型(如 digit, blank, sign, ., e),值为下一个状态。
  2. 遍历字符串

    • 使用 trim() 方法去除字符串两端的空白字符。
    • 遍历处理后的字符串,逐个字符进行分类和状态转换。
  3. 字符分类

    • 数字字符(0-9):转换为 digit
    • 空格字符( ):转换为 blank
    • 小数点字符(.):保持不变。
    • 指数字符(eE):转换为 e
    • 符号字符(+-):转换为 sign
  4. 状态转换

    • 根据当前字符和当前状态,在 graph 中查找下一个状态。
    • 如果找不到对应的转换规则(即 state === undefined),则返回 false,表示字符串不是有效数字。
  5. 最终状态检查

    • 遍历结束后,检查最终状态是否为合法的终止状态(3, 5, 6)。只有当最终状态为这些状态之一时,才返回 true,否则返回 false

控制流图(CFG)

flowchart TDA[开始] --> B{字符串为空?}B -->|Yes| E[返回 false]B -->|No| C[初始化状态为0]C --> D[去除空白字符]D --> F[遍历字符串]F --> G{字符类型是什么?}G -->|digit| H[转换为 digit]G -->|blank| I[转换为 blank]G -->|.| J[转换为 .]G -->|e 或 E| K[转换为 e]G -->|+ 或 -| L[转换为 sign]H --> M[查找下一个状态]I --> MJ --> MK --> ML --> MM --> N{找到下一个状态?}N -->|No| O[返回 false]N -->|Yes| P[更新状态]P --> Q{遍历结束?}Q -->|No| FQ -->|Yes| R{最终状态合法?}R -->|No| S[返回 false]R -->|Yes| T[返回 true]

关键点说明

  1. 状态机设计

    • 状态机的核心是 graph 对象,它定义了从一个状态到另一个状态的转换规则。
    • 每个状态都有不同的字符类型可以触发状态转换,例如在状态 0 下遇到 digit 会转移到状态 6
  2. 字符分类逻辑

    • 通过条件判断将字符分为五类:digitblank.esign
    • 这种分类简化了状态转换的复杂度,使得代码更加简洁易读。
  3. 循环遍历与状态更新

    • 使用 for...of 循环遍历字符串中的每个字符。
    • 在每次迭代中,根据当前字符和当前状态查找下一个状态,并更新状态变量 state
    • 如果在任何时刻找不到合适的转换规则,则立即返回 false
  4. 最终状态检查

    • 遍历结束后,检查最终状态是否为合法的终止状态(3, 5, 6)。
    • 只有当最终状态为这些状态之一时,才认为字符串是一个有效的数字,返回 true;否则返回 false

示例解析

console.log(isNumber("1E9")) 为例:

  1. 初始化状态为 0
  2. 去除空白字符后,字符串为 "1E9"
  3. 遍历第一个字符 '1'
    • 类型为 digit,根据 graph 规则从状态 0 转移到状态 6
  4. 遍历第二个字符 'E'
    • 类型为 e,根据 graph 规则从状态 6 转移到状态 4
  5. 遍历第三个字符 '9'
    • 类型为 digit,根据 graph 规则从状态 4 转移到状态 5
  6. 遍历结束,最终状态为 5,属于合法的终止状态,因此返回 true

希望这个详细的解释能够帮助你更好地理解这段代码的工作原理。
image

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vs2019项目报错:文件中的类都不能进行设计,解决办法_无法设计基类system.void

文件中的类都不能进行设计,因此未能为该文件显示设计器。设计器检查出文件中有以下类: Form1 --- 无法设计基类“System.Void”。 出现上述错误,解决办法如下: 关闭所有设计窗口(例如form1.cs(设计)),菜单栏生成,清理解决方案,关闭vs2022,重新启动vs2022打开你的项目…

关于VSCode的c/c++环境配置

适用于Windows的VSCode的c/c++环境配置c/c++环境配置写给 初学C/C++的 保姆级 VSCode环境配置第一步 下载VScode 找到官网点下载就好啦下载安装完成之后,启动!点击左侧“拓展”图标下载中文拓展安装好后重启 别关 留着备用 第二步 下载c/c++编译器 这里我使用MinGw实际上 Mi…

G75 拉插 CF622F The Sum of the k-th Powers

视频链接: The Sum of the k-th Powers - 洛谷 | 计算机科学教育新生态// 拉插 O(klogn) #include <iostream> #include <cstring> #include <algorithm> using namespace std;#define LL long long const int N=1e6+10,mod=1e9+7; int n,k; LL ml[N],mr…

Cline 免费插件 + Qwen2.5 大模型,零经验也能开发“对联王”微信小程序

本文详细介绍了如何利用免费的 Cline 插件辅助开发一款名为“对联王”的微信小程序,特别适合希望在春节期间创作春联的用户。文章不仅比较了 Cline 与 Cursor 两款工具的优缺点,还分享了作者实际操作中的经验和建议。通过具体步骤演示,即使是编程新手也能跟随指导,结合微信…

实现无感刷新Token技术:.Net Web API与axios的完美结合

备忘:https://mp.weixin.qq.com/s?__biz=MjM5MDE5MDM5NA==&mid=2449944319&idx=1&sn=71e84d8ee24769e77b19ca8367333b8f&chksm=b1bb10aa86cc99bc2f20686354e8184023278de74dba857a42d720dc47fabb654c12ecb83524&scene=21#wechat_redirect 我们都知道Toke…

方法引用与lambda底层原理Java方法引用、lambda能被序列化么?

系列文章目录和关于我 0.引入 最近笔者使用flink实现一些实时数据清洗(从kafka清洗数据写入到clickhouse)的功能,在编写flink作业后进行上传,发现运行的时候抛出:java.io.NotSerializableException,错误消息可能类似于 “org.apache.flink.streaming.api.functions.MapFu…

Java方法引用、lambda如何序列化方法引用与lambda底层原理

系列文章目录和关于我 0.引入 最近笔者使用flink实现一些实时数据清洗(从kafka清洗数据写入到clickhouse)的功能,在编写flink作业后进行上传,发现运行的时候抛出:java.io.NotSerializableException,错误消息可能类似于 “org.apache.flink.streaming.api.functions.MapFu…

2024年秋学期 分析力学(理论物理基础Ⅰ)笔记

内容说明舍去了哈密顿雅可比方程等内容 删去了振动相关的一些模型,如参数共振等 授课难度疑似过大了一点(毕竟才半个学期),协变相关内容疑似太tm多了 有心力场模块笔记有所省略,部分笔记不排除记录有误的可能性 部分章节间未换页笔记正文拉格朗日力学及其协变形式 哈密顿力…

find_package()使用指南

关于find_package() 在使用cmake引用第三方库(比如OpenCV)时,我们总是使用find_package()这个指令来实现对包的查找(比如find_package(OpenCV))。调用完后就可以使用一些似乎凭空出现的变量如${OpenCV_INCLUDE_DIRS}以及${OpenCV_LIBS},分别指示了OpenCV库的头文件路径以及各个…

音视频:JavaCV 采集桌面画面并显示的方法

需要进行简单的音视频编程,如果不是特别熟悉C/C++,那么JavaCV应该是比较好的选择,下面记录一下使用JavaCV采集桌面数据的方法。 使用FFmpegFrameGrabber采集桌面数据,指定输入源为desktop,format设置为gdigrab。参考雷神的博客:https://blog.csdn.net/leixiaohua1020/art…

《深入理解Mybatis原理》MyBatis事务管理机制

概述 对数据库的事务而言,应该具有以下几点:创建(create)、提交(commit)、回滚(rollback)、关闭(close)。对应地,MyBatis将事务抽象成了Transaction接口:MyBatis的事务管理分为两种形式:使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(…

【Python基础】Python虚拟环境

什么是Python环境 要搞清楚什么是虚拟环境,首先要清楚Python的环境指的是什么。当我们在执行python test.py时,思考如下问题:python哪里来? 这个主要归功于配置的系统环境变量PATH,当我们在命令行中运行程序时,系统会根据PATH配置的路径列表依次查寻是否有可执行文件pyth…