当前位置: 首页 > news >正文

LeetCode 393 - UTF-8 编码验证

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码讲解
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

UTF-8 是目前互联网上使用最广泛的字符编码方式之一,它的灵活性和兼容性使得我们几乎在所有系统中都能正常显示各种语言的字符。
不过,正因为 UTF-8 的变长特性(1~4 个字节表示一个字符),验证一个字节序列是否是合法的 UTF-8 编码并不那么直观。

这道题(LeetCode 393)让我们从底层去“读懂” UTF-8 的规则,通过判断一个整数数组是否能组成合法的 UTF-8 字节序列,间接地理解字符编码的逻辑。

这其实不仅是算法题,更是一道关于底层数据表示和系统字符编码理解的题。

描述

我们需要判断一个整数数组 data 是否是合法的 UTF-8 编码。

每个整数(0 <= data[i] <= 255)代表一个字节,也就是 8 位二进制数。
UTF-8 的编码规则如下:

字节数格式(二进制)说明
1 字节0xxxxxxx普通 ASCII 字符
2 字节110xxxxx 10xxxxxx双字节字符
3 字节1110xxxx 10xxxxxx 10xxxxxx三字节字符
4 字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx四字节字符

规律总结:

  • 第一个字节告诉我们当前字符有多少个字节;
  • 后续的字节必须以 10 开头;
  • 所有不满足这两条规则的情况都是非法编码。

题解答案

整体思路可以分成两步:

  1. 统计当前字节开头的 1 的数量
    这个数量决定了当前字符占用多少字节(例如 110xxxxx 就说明需要 2 个字节)。

  2. 验证后续字节
    接下来的若干个字节(数量 = 上一步统计的结果 - 1)必须以 10 开头。
    只要有任何一个不满足条件,就立即返回 false。

整个过程一次遍历即可完成。

题解代码分析

下面是完整的 Swift 代码实现,可以直接运行:

import Foundationclass UTF8Validator {func validUtf8(_ data: [Int]) -> Bool {var remainingBytes = 0  // 记录当前还需要的字节数for byte in data {// 只取最低 8 位let b = byte & 0xFFif remainingBytes == 0 {// 判断当前字节的前缀有多少个 1if (b >> 5) == 0b110 {        // 110xxxxx -> 2 字节remainingBytes = 1} else if (b >> 4) == 0b1110 { // 1110xxxx -> 3 字节remainingBytes = 2} else if (b >> 3) == 0b11110 { // 11110xxx -> 4 字节remainingBytes = 3} else if (b >> 7) == 1 {       // 10xxxxxx 开头不合法return false}} else {// 检查后续字节必须以 10 开头if (b >> 6) != 0b10 {return false}remainingBytes -= 1}}// 所有字节验证完后,remainingBytes 必须为 0return remainingBytes == 0}
}

代码讲解

  • b >> n 表示右移 n 位,检查二进制前缀;
  • (b >> 5) == 0b110 判断是否以 110 开头;
  • remainingBytes 表示当前还需要多少个后续字节;
  • 如果遇到非法的 10xxxxxx 开头字节,立刻返回 false
  • 最后检查 remainingBytes == 0,确保整个序列刚好结束,没有“半个字符”残留。

这段逻辑跟 UTF-8 的标准一一对应,非常直观。

示例测试及结果

我们来验证几个典型例子

let validator = UTF8Validator()print(validator.validUtf8([197, 130, 1]))
// 输出: true
// 解释:11000101 10000010 00000001
// 110 开头说明第一个字符是 2 字节编码,后面的 10xxxxxx 是合法延续字节。
// 最后的 00000001 是单字节字符,全序列合法。print(validator.validUtf8([235, 140, 4]))
// 输出: false
// 解释:11101011 10001100 00000100
// 第一个是 3 字节字符 (1110 开头),第二个没问题 (10 开头),但第三个不是 10 开头,非法。print(validator.validUtf8([0b11100010, 0b10000010, 0b10101100]))
// 输出: true
// 这是字符 “€”(欧元符号)的 UTF-8 编码,合法。

输出结果:

true
false
true

时间复杂度

整段代码只需要遍历数组一次,每个字节的检查是 O(1) 操作。

时间复杂度:O(n),其中 n 是字节数。

空间复杂度

整个过程只用了一个变量 remainingBytes 来保存状态,没有使用额外空间。

空间复杂度:O(1)

总结

这道题的关键在于理解 UTF-8 的编码规则,而不是写复杂的算法。
它的难点在于逻辑判断:

  • 如何判断字符头;
  • 如何验证后续字节;
  • 如何保证整体字节数刚好匹配。

从工程角度看,这种验证逻辑常用于:

  • 文件或网络传输时判断数据是否被截断;
  • 数据库或日志系统中检测是否有乱码;
  • 编写底层解析器或协议时(比如 JSON/HTTP)进行编码合法性校验。

这道题不仅能锻炼逻辑思维,还能让你对 “文本是如何变成二进制存储的” 有更直观的理解。

http://www.dtcms.com/a/460887.html

相关文章:

  • Ruby 条件判断
  • 车企数据治理平台化实战:从数据孤岛到全链路治理的架构演进
  • Subword分词方法的BPE与BBPE
  • 对比的网站建设注册网站需要营业执照吗
  • 郑州网站建设排行榜易语言网站做软件
  • npm error Could not resolve dependency:
  • arcgis矢量数据转为标准geojson格式
  • 解决 React 项目初始化(npx create-react-app)速度慢的 7 个实用方案
  • 第5篇 如何计算两个坐标点距离--opencv图像中的两个点
  • powerShell无法执行npm问题
  • npm install sqlite3时报错解决
  • Docker compose-配置阿里云DNS加速访问百炼大模型
  • 使用HTML和Python开发街霸游戏
  • npm相关知识
  • asp.net 网站提速.net做网站之前设置
  • 化妆品网站建设方案项目书手机网站模板建站
  • QT/C++中的哈希表
  • Java学习之旅第二季-14:super关键字与final关键字
  • 【Unity】uNet游戏服务端框架(一)服务端架构设计
  • 深圳企业营销型网站建设优创智汇高端网站建设
  • mysql数据库备份
  • 22.shell编程实战(一)
  • PyTorch、ONNX Runtime、Hugging Face、NVIDIA Triton 和 LangChain 五个概念的关系详解
  • 【云原生】Neo4j 图数据库从搭建到项目使用深度详解
  • 关于网站开发的技术博客女装网站模板
  • Kubernetes(K8s)全场景命令宝典:从新手入门到故障排查全覆盖
  • 基于protobuf实现网络版本通讯录(protobuf 0基础可看)
  • 开源3d数字人学习笔记2025
  • 四大名著智能可视化推演平台
  • 成像系统(十四-2:《手机影像系统揭秘(二):ISP后端处理 - 画质增强与风格化》):从LED冬奥会、奥运会及春晚等大屏,到手机小屏,快来挖一挖里面都有什么