LeetCode 393. UTF-8 编码验证 / 599. 两个列表的最小索引总和 / 2044. 统计按位或能得到最大值的子集数目

135 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

393. UTF-8 编码验证

2022.3.13 每日一题

题目描述

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

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

  1. 对于 1 字节 的字符,字节的第一位设为 0 ,后面 7 位为这个符号的 unicode 码。
  2. 对于 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 字节的数据。

示例 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 开头,所以是不符合规则的。

提示:

1 <= data.length <= 2 * 10^4 0 <= data[i] <= 255

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ut… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

按照所给规律判断就行了

class Solution {
    public boolean validUtf8(int[] data) {
        //看例子得到这个数组表示的字符可能不只是一个,可能是多个
        //然后怎么判断呢,其实挨个判断就可以了
        //如果开头是0,那么这个字符只有一个字节,可行,跳过
        //如果开头有四个1以上或者只有1个1,直接false
        //如果有两个到四个1,那么就看后面两个到四个数,是否开头都是10,不是的话false

        int n = data.length;
        int count = 0;
        for(int i = 0; i < n; i++){
            int num = data[i];
            //如果是后面的字节,但是前两个位置不是10,那么直接false
            if(count > 0){
                if((num >> 6) != 2)
                    return false;
                else
                    count--;
            //如果开头是0,那么是单字节
            }else if((num >> 7) == 0)
                continue;
            //如果有4个以上的1或者1个1,那么false
            else if((num >> 3) > 30 || (num >> 6) == 2)
                return false;
            else if((num >> 5) == 6)
                count = 1;
            else if((num >> 4) == 14)
                count = 2;
            else if((num >> 3) == 30)
                count = 3;
        }
        return count == 0 ? true : false;
    }
}

599. 两个列表的最小索引总和

2022.3.14 每日一题

题目描述

假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。

你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设答案总是存在。

示例 1:

输入: list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 输出: ["Shogun"] 解释: 他们唯一共同喜爱的餐厅是“Shogun”。

示例 2:

输入:list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["KFC", "Shogun", "Burger King"] 输出: ["Shogun"] 解释: 他们共同喜爱且具有最小索引和的餐厅是“Shogun”,它有最小的索引和1(0+1)。

提示:

1 <= list1.length, list2.length <= 1000 1 <= list1[i].length, list2[i].length <= 30 list1[i] 和 list2[i] 由空格 ' ' 和英文字母组成。 list1 的所有字符串都是 唯一 的。 list2 中的所有字符串都是 唯一 的。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/mi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

我本以为我这种方法是高效方法,没想到反而低了 还不如用哈希表

class Solution {
    public String[] findRestaurant(String[] list1, String[] list2) {
        int l1 = list1.length;
        int l2 = list2.length;
        int max = l1 - 1 + l2 - 1;
        List<String> list = new ArrayList<>();
        for(int i = 0; i <= max; i++){
            for(int first = 0; first <= i && first < l1; first++){
                if(i - first < l2 && list1[first].equals(list2[i - first]))
                    list.add(list1[first]);
            }
            if(list.size() > 0)
                break;
        }
        return list.toArray(new String[0]);
    }
}

2044. 统计按位或能得到最大值的子集数目

2022.3.15 每日一题

题目描述

给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。

如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR ... OR a[a.length - 1](下标从 0 开始)。

示例 1:

输入:nums = [3,1]
输出:2
解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :
[3]
[3,1]

示例 2:

输入:nums = [2,2,2] 输出:7 解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。

示例 3:

输入:nums = [3,2,1,5] 输出:6 解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 : -[3,5] -[3,1,5] -[3,2,5] -[3,2,1,5] -[2,5] -[2,1,5]

提示:

1 <= nums.length <= 16 1 <= nums[i] <= 10^5

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution {
    public int countMaxOrSubsets(int[] nums) {
        //因为或是有1就是1,所以先统计每个数哪些数位是1
        //每个位置都有一个数肯定是最大的,但是有重复的好像不太好处理
        //那么只能回溯或者状压了

        int n = nums.length;
        int max = 0;
        int count = 0;

        int mask = 1 << n;
        for(int i = 1; i < mask; i++){
            int temp = 0;
            for(int j = 0; j < n; j++){
                if(((i >> j) & 1) == 1){
                    temp |= nums[j];
                }
            }
            if(temp > max){
                max = temp;
                count = 1;
            }else if(temp == max)
                count++;
        }
        return count;
    }
}