每日一题 --- 393. UTF-8 编码验证[力扣][Go]

简介: 每日一题 --- 393. UTF-8 编码验证[力扣][Go]

题目:

给定一个表示数据的整数数组 data ,返回它是否为有效的 UTF-8 编码。

UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:

对于 1 字节 的字符,字节的第一位设为 0 ,后面 7 位为这个符号的 unicode 码。

对于 n 字节 的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为 0 ,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 unicode 码。

这是 UTF-8 编码的工作方式:

Char. number range | UTF-8 octet sequence

(hexadecimal) | (binary)

--------------------±--------------------------------------------

0000 0000-0000 007F | 0xxxxxxx

0000 0080-0000 07FF | 110xxxxx 10xxxxxx

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

注意:输入是整数数组。只有每个整数的 最低 8 个有效位 用来存储数据。这意味着每个整数只表示 1 字节的数据。

解题代码:

官方题解

// 位运算
// mask1 = 10000000
// mask2 = 11000000
const mask1, mask2 = 1 << 7, 1<<7 | 1<<6
// 判断占了几个字节
func getBytes(num int) int {
  if num&mask1 == 0 {
    return 1
  }
  n := 0
  // >>=  即 mask = mask>>1
  for mask := mask1; num&mask != 0; mask >>= 1 {
    n++
    if n > 4 {
      return -1
    }
  }
  if n >= 2 {
    return n
  }
  return -1
}
func validUtf8(data []int) bool {
  for index, m := 0, len(data); index < m; {
    n := getBytes(data[index])
    // 如果超出范围就返回 false
    if n < 0 || index+n > m {
      return false
    }
    // 遍历这个字节处第一个元素外应该有的元素
    for _, ch := range data[index+1 : index+n] {
      // ch&mask2 != mask1 用于判断ch前两位数是否为 10
      if ch&mask2 != mask1 {
        return false
      }
    }
    // 跳过该字节应有的数字数
    index += n
  }
  return true
}

我的题解,测试用例通过,提交出错

var binaryPre = []string{"0","110","1110","11110"}
func validUtf8(data []int) bool {
  var binary []string
  // 将data转换为二进制
  for _, datum := range data {
    binary = append(binary, int2binary(datum))
  }
  // 判断第几个是几字节的开始
  var m = make(map[int]int)
  for i := 0; i < len(binary); i++ {
    if strings.Index(binary[i],binaryPre[0]) == 0{
      m[i] = 0
    } else if strings.Index(binary[i],binaryPre[1]) == 0 {
      m[i] = 1
      i += 1
    } else if strings.Index(binary[i],binaryPre[2]) == 0 {
      m[i] = 2
      i += 2
    } else if strings.Index(binary[i],binaryPre[3]) == 0 {
      m[i] = 3
      i += 3
    } else {
      return false
    }
  }
  for i1, i2 := range m {
    if i2 != 0{
      for i := i2 - 1; i >= 0; i-- {
        if strings.Index(binary[i1 + i2 -i], "10") != 0 {
          return false
        }
      }
    }
  }
  return true
}
func int2binary(n int) string {
  var ans string
  for n != 0 {
    ans = strconv.Itoa(n % 2) + ans
    n = n/2
  }
  for len(ans) < 8 {
    ans = "0" + ans
  }
  return ans
}


相关文章
|
6月前
|
Go C++
【力扣】2696. 删除子串后的字符串最小长度(模拟 栈 C++ Go实现栈)
【2月更文挑战第18天】2696. 删除子串后的字符串最小长度(模拟 栈 C++ Go实现栈)
59 6
|
6月前
|
Go C++
【力扣】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)
【2月更文挑战第17天】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)
42 8
每日一题 --- 942. 增减字符串匹配[力扣][Go]
每日一题 --- 942. 增减字符串匹配[力扣][Go]
每日一题 --- 942. 增减字符串匹配[力扣][Go]
|
算法 Go
每日一题 --- 442. 数组中重复的数据[力扣][Go]
每日一题 --- 442. 数组中重复的数据[力扣][Go]
每日一题 --- 442. 数组中重复的数据[力扣][Go]
每日一题 --- 933. 最近的请求次数[力扣][Go]
每日一题 --- 933. 最近的请求次数[力扣][Go]
每日一题 --- 933. 最近的请求次数[力扣][Go]
每日一题 --- 713. 乘积小于 K 的子数组[力扣][Go]
每日一题 --- 713. 乘积小于 K 的子数组[力扣][Go]
每日一题 --- 713. 乘积小于 K 的子数组[力扣][Go]
每日一题 --- 606. 根据二叉树创建字符串[力扣][Go]
每日一题 --- 606. 根据二叉树创建字符串[力扣][Go]
每日一题 --- 606. 根据二叉树创建字符串[力扣][Go]
|
Go 索引
每日一题 ---- 599. 两个列表的最小索引总和[力扣][Go]
每日一题 ---- 599. 两个列表的最小索引总和[力扣][Go]
每日一题 ---- 599. 两个列表的最小索引总和[力扣][Go]
每日一题 --- 590. N 叉树的后序遍历[力扣][Go]
每日一题 --- 590. N 叉树的后序遍历[力扣][Go]
每日一题 --- 590. N 叉树的后序遍历[力扣][Go]
每日一题 --- 二叉树的遍历[力扣][Go]
每日一题 --- 二叉树的遍历[力扣][Go]
每日一题 --- 二叉树的遍历[力扣][Go]