393. UTF-8 Validation

Task text is translated from Russian for the selected interface language. Code is left unchanged.

Дан integer array data, представляющий данные, return, является ли это допустимой UTF-8 кодировкой (т.е. переводится в последовательность допустимых UTF-8 закодированных символов).

Символ в UTF-8 может быть от 1 до 4 байтов в длину, при этом соблюдаются следующие правила:

Для 1-байтового символа первый бит — 0, за которым следует его Unicode код.

Для n-байтового символа первые n битов — все единицы, (n + 1)-й бит — 0, за которыми следуют n - 1 байт с наиболее значимыми 2 битами, равными 10.

Это работает следующим образом:

Количество байтов | UTF-8 Октетная последовательность

| (бинарная)

--------------------+-----------------------------------------

1 | 0xxxxxxx

2 | 110xxxxx 10xxxxxx

3 | 1110xxxx 10xxxxxx 10xxxxxx

4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

x обозначает бит в бинарной форме байта, который может быть как 0, так и 1.

Примечание: Input представляет собой array целых чисел. Используются только 8 младших значимых битов каждого целого числа. Это означает, что каждое integer представляет только 1 байт данных.

Example:

Input: data = [197,130,1]

Output: true

Explanation: data represents the octet sequence: 11000101 10000010 00000001.

It is a valid utf-8 encoding for a 2-bytes character followed by a 1-byte character.

C# solution

matched/original
public class Solution {
    public bool ValidUtf8(int[] data) {
        int nBytes = 0;
        foreach (int num in data) {
            string binRep = Convert.ToString(num, 2).PadLeft(8, '0').Substring(0, 8);
            if (nBytes == 0) {
                foreach (char bit in binRep) {
                    if (bit == '0') break;
                    nBytes++;
                }
                if (nBytes == 0) continue;
                if (nBytes == 1 || nBytes > 4) return false;
            } else {
                if (!(binRep[0] == '1' && binRep[1] == '0')) return false;
            }
            nBytes--;
        }
        return nBytes == 0;
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public bool ValidUtf8(vector<int>& data) {
        int nBytes = 0;
        foreach (int num in data) {
            string binRep = Convert.ToString(num, 2).PadLeft(8, '0').Substring(0, 8);
            if (nBytes == 0) {
                foreach (char bit in binRep) {
                    if (bit == '0') break;
                    nBytes++;
                }
                if (nBytes == 0) continue;
                if (nBytes == 1 || nBytes > 4) return false;
            } else {
                if (!(binRep[0] == '1' && binRep[1] == '0')) return false;
            }
            nBytes--;
        }
        return nBytes == 0;
    }
}

Java solution

matched/original
public class Main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.validUtf8(new int[]{197, 130, 1})); // true
        System.out.println(solution.validUtf8(new int[]{235, 140, 4})); // false
    }
}

class Solution {
    public boolean validUtf8(int[] data) {
        int nBytes =

JavaScript solution

matched/original
var validUtf8 = function(data) {
    let nBytes = 0;
    for (let num of data) {
        let binRep = num.toString(2).padStart(8, '0').slice(-8);
        if (nBytes === 0) {
            for (let bit of binRep) {
                if (bit === '0') break;
                nBytes++;
            }
            if (nBytes === 0) continue;
            if (nBytes === 1 || nBytes > 4) return false;
        } else {
            if (!(binRep[0] === '1' && binRep[1] === '0')) return false;
        }
        nBytes--;
    }
    return nBytes === 0;
};

Python solution

matched/original
class Solution:
    def validUtf8(self, data):
        n_bytes = 0

        for num in data:
            bin_rep = format(num, '#010b')[-8:]

            if n_bytes == 0:
                for bit in bin_rep:
                    if bit == '0': break
                    n_bytes += 1

                if n_bytes == 0:
                    continue

                if n_bytes == 1 or n_bytes > 4:
                    return False
            else:
                if not (bin_rep[0] == '1' and bin_rep[1] == '0'):
                    return False

            n_bytes -= 1

        return n_bytes == 0

Go solution

matched/original
package main

import (
    "fmt"
)

func validUtf8(data []int) bool {
    nBytes := 0
    for _, num := range data {
        binRep := fmt.Sprintf("%08b", num)[-8:]
        if nBytes == 0 {
            for _, bit := range binRep {
                if bit == '0' {
                    break
                }
                nBytes++
            }
            if nBytes == 0 {
                continue
            }
            if nBytes == 1 || nBytes > 4 {
                return false
            }
        } else {
            if !(binRep[0] == '1' && binRep[1] == '0') {
                return false
            }
        }
        nBytes--
    }
    return nBytes == 0
}

func main() {
    data1 := []int{197, 130, 1}
    data2 := []int{235, 140, 4}
    fmt.Println(validUtf8(data1)) // true
    fmt.Println(validUtf8(data2)) // false
}

Algorithm

Начните обработку целых чисел в данном arrayе одно за другим. Для каждого целого числа получите его двоичное представление в виде строки. Поскольку целые числа могут быть очень большими, следует учитывать только 8 младших значимых битов данных и отбросить остальные, как указано в условии задачи. После этого шага у вас должно быть 8-битное или 1-байтовое строковое представление целого числа. Назовем эту строку bin_rep.

Далее нужно рассмотреть два сценария. Первый — мы находимся в процессе обработки некоторого UTF-8 закодированного символа. В этом случае нужно просто проверить первые два бита строки и посмотреть, равны ли они "10", т.е. наиболее значимые два бита целого числа равны 1 и 0. bin_rep[:2] == "10". Второй сценарий — мы уже обработали несколько допустимых UTF-8 символов и должны начать обработку нового UTF-8 символа. В этом случае нужно посмотреть на префикс строкового представления и посчитать количество единиц, которые мы встречаем до первой нули. Это скажет нам, каков размер следующего UTF-8 символа.

Продолжайте обрабатывать целые числа arrayа таким образом, пока не обработаете их все или не обнаружите недопустимый сценарий.

Теперь давайте перейдем к реализации этого Algorithmа.

😎

Vacancies for this task

Active vacancies with overlapping task tags are shown.

All vacancies
There are no active vacancies yet.