1. 程式人生 > 其它 >393. UTF-8 編碼驗證

393. 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
給定一個表示資料的整數陣列,返回它是否為有效的 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
給定一個表示資料的整數陣列,返回它是否為有效的 utf-8 編碼。

注意:
輸入是整數陣列。只有每個整數的 最低 8 個有效位 用來儲存資料。這意味著每個整數只表示 1 位元組的資料。

示例 1:

data = [197, 130, 1], 表示 8 位的序列: 11000101 10000010 00000001.

返回 true 。
這是有效的 utf-8 編碼,為一個2位元組字元,跟著一個1位元組字元。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/utf-8-validation
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution {

    private int index;

    private int n;

    private String data;

    private String toBinary(int n) {
        StringBuilder ret = new StringBuilder();
        do {
            ret.append(n % 2);
            n /= 2;
        } while (n != 0);
        for (int i = ret.length(); i < 8; ++i) {
            ret.append(0);
        }

        return ret.reverse().toString();
    }

    public boolean validUtf8(int[] data) {
        StringBuilder sb = new StringBuilder();
        for (int i : data) {
            String s = toBinary(i);
            if (s.length() > 8) {
                return false;
            }
            sb.append(s);
        }
        this.index = 0;
        this.n = sb.length();
        this.data = sb.toString();
        
        while (index < n) {
            int byteNum = getN();
            if (byteNum == 1) {
                if (this.data.charAt(index) == '1') {
                    return false;
                }
                index += 8;
            } else {
                if (byteNum > 4) {
                    return false;
                }
                while (--byteNum > 0) {
                    index += 8;
                    if (index >= n) {
                        return false;
                    }
                    if (this.data.charAt(index) != '1' || this.data.charAt(index + 1) != '0') {
                        return false;
                    }
                }
                index += 8;
            }
        }
        return true;
    }

    public int getN() {
        if (data.charAt(index) == '0') {
            return 1;
        } else {
            int cnt = 0;
            int p = index;
            while (p < n && data.charAt(p) == '1') {
                cnt++;
                p++;
            }
            return cnt;
        }
    }
}
心之所向,素履以往 生如逆旅,一葦以航