题目描述
给定一个表示数据的整数数组 data ,返回它是否为有效的 UTF-8 编码。
UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
对于 1 字节 的字符,字节的第一位设为 0 ,后面 7 位为这个符号的 unicode 码。
对于 n 字节 的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为 0 ,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 unicode 码。
这是 UTF-8 编码的工作方式:
注意:输入是整数数组。只有每个整数的 最低 8 个有效位 用来存储数据。这意味着每个整数只表示 1 字节的数据。
示例 1:
输入:data = [197,130,1]
输出:true
解释:数据表示字节序列:11000101 10000010 00000001。
这是有效的 utf-8 编码,为一个 2 字节字符,跟着一个 1 字节字符。
示例 2:
输入:data = [235,140,4]
输出:false
解释:数据表示 8 位的序列: 11101011 10001100 00000100.
前 3 位都是 1 ,第 4 位为 0 表示它是一个 3 字节字符。
下一个字节是开头为 10 的延续字节,这是正确的。
但第二个延续字节不以 10 开头,所以是不符合规则的。
思路分析
这道题我读了一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边一边,不是很懂。。。。。。。。。
于是摸索着做,
再离谱点?
又重新去看了看题,想了半天,实际上这道题不难,思路也很简单,就是我没看懂题 属是有点蠢。
简单来说:题目所给的数组是int型,数值是多少无关紧要。先全部转换成8位二进制。
转为二进制之后 只有几下几种情况:
- 0XXXXXXX (一字节)
- 10XXXXXX
- 110XXXXX (二字节)
- 1110XXXX (三字节)
- 11110XXX (四字节)
若为一字节 0XXXXXXX 的形式,则无视。
若为二字节 110XXXXX 的形式,则后续需要跟一个10XXXXXX。
若为三字节 1110XXXX 的形式,则后续需要跟二个10XXXXXX。
若为四字节 11110XXX 的形式,则后续需要跟三个10XXXXXX。
也就是说 N字节 后续需要跟 N-1个 10XXXXXX。
比如 所给的示例:[197,130,1]
首先转换为二进制: 11000101 10000010 00000001。
第一个为110XXXXX ,二字节,则要求后面要跟一个10XXXXXX, ,而所给的第二个刚好是 10开头的。符合要求。继续,第三个是0开头的,无视。故该示例True。
第二个示例:[235,140,4]
转为二进制, 11101011 10001100 00000100.
第一个是1110XXXX, 则后续需要跟两个10XXXXXX。而题目所给的第二个是10开头,第三个是0开头的,并不是10开头的,所以没有满足 直接返回False。
所以开始说的那个条件,遇到0开头直接无视,这里的无视是又条件的无视,满足了前方需要的10XXXXXX的个数时,才能无视。若10XXXXXX的个数没有得到满足而出现了0开头的数,则直接False。
思路就简单了。
- 全部转换成二进制存起来放到temp里
- 遍历temp,判断当前是哪一个情况开头的,如果是0则指针往后移。
- 若为 110 、1110、11110、则对应看他后面是否跟着相应数量的 10XXXXXX, 若个数符合 ,则指针相应后移 2 ,3 ,4。
完整代码
class Solution:
def validUtf8(self, data: List[int]) -> bool:
def continuous(idx,num):
for i in range(idx+1,idx+num+1):
if data[i][:2] != '10':
return False
return True
for i in range(len(data)): # 全变成二进制
data[i] = "{:08b}".format(data[i])
p = 0
while p < len(data):
if data[p][0] == '0':
p +=1
elif data[p][:3] == '110' and p+1 < len(data):
if not continuous(p,1):
return False
p +=2
elif data[p][:4] == '1110' and p+2 < len(data):
if not continuous(p,2):
return False
p +=3
elif data[p][:5] == '11110' and p+3 < len(data):
if not continuous(p,3):
return False
p +=4
else:
return False
return True