393. UTF-8 编码验证 / 139. 单词拆分

393. UTF-8 编码验证【中等题】【每日一题】

思路:【暴力模拟】

  1. 自己写的,时间9ms,比不了大佬们。
  2. 先将data中的所有数据都给转成长度为8的二进制字符串。
  3. 定义一个函数judge对传入的字符串进行判断(传入字符串长度必为8),如果第1位为0,则函数返回0;如果前两位是10,则函数返回-1;如果前三位是110,则函数返回1;如果前4位是1110,则函数返回2;如果前5位是11110,则函数返回3。
  4. 定义变量need用来存储需要的前缀为10的字符串个数,cnt用来统计已经遍历到的前缀为10的字符串个数,flag用来标志是否需要统计前缀为10的字符串,初值为false,即不需要统计。
  5. 遍历字符串数组bytes(就是第1步中data中的所有数据转换为8位二进制字符串之后存储的数组),定义当前字符串的状态进行判断(调用judge函数),将状态值存入cur变量。
  6. 如果cur不为0,则: 判断是否需要统计10字符串的个数, 为true,需要统计,那么如果cur等于 -1,则cnt++,如果cur不为-1,则整个函数直接返回false,如果cnt等于need,那么就将flag置为false,并将cnt归0;
    为false,不需要统计,那么如果cur 等于
    -1,那么整个函数直接返回false,否则,当前cur即表示接下来要统计的10字符串的数量,即need=cur,同时flag置为true,表示开始计数。
  7. 如果cur等于0,那么判断现在是否正在统计10字符串,即flag是否为true,是,那么返回false。
  8. 整个bytes数组遍历结束之后,如果flag为true,说明仍在统计10字符串,那么返回false,如果为false,说明已经结束了,返回true,简化之后即为,返回
    !flag。

代码:

class Solution {
    public boolean validUtf8(int[] data) {
        int len = data.length;
        String[] bytes = new String[len];
        for (int i = 0; i < len; i++) {
            String binaryString = Integer.toBinaryString(data[i]);
            if (binaryString.length() == 8){
                bytes[i] = binaryString;
            }else {
                int k = binaryString.length();
                StringBuilder sb = new StringBuilder(binaryString);
                for (int j = 0; j < 8-k; j++) {
                    sb.insert(0,0);
                }
                bytes[i] = sb.toString();
            }
        }
        int need = 0,cnt = 0;
        boolean flag = false;
        for (int i = 0; i < len; i++) {
            int cur = judge(bytes[i]);
            if (cur != 0){
                if (flag){
                    if (cur == -1){
                        cnt++;
                    }else {
                        return false;
                    }
                    if (cnt == need){
                        flag = false;
                        cnt = 0;
                    }
                }else {
                    if (cur == -1){
                        return false;
                    }else {
                        need = cur;
                        flag = true;
                    }
                }
            }else {
                if (flag){
                    return false;
                }
            }
        }
        return !flag;
    }
    public int judge(String str){
        if (str.charAt(0) == '0'){
            return 0;
        }
        if ("10".equals(str.substring(0,2))){
            return -1;
        }
        if ("110".equals(str.substring(0,3))){
            return 1;
        }
        if ("1110".equals(str.substring(0,4))){
            return 2;
        }
        if ("11110".equals(str.substring(0,5))){
            return 3;
        }
        return -1;
    }
}

写完题解之后发现我的代码好像可以优化一下,不过好像并没什么卵用,不用位运算时间还是没有提升~
优化后代码:

class Solution {
    public boolean validUtf8(int[] data) {
        int need = 0,cnt = 0;
        boolean flag = false;
        for (int datum : data) {
            String binaryString = Integer.toBinaryString(datum);
            if (binaryString.length() != 8) {
                int k = binaryString.length();
                StringBuilder sb = new StringBuilder(binaryString);
                for (int j = 0; j < 8 - k; j++) {
                    sb.insert(0, 0);
                }
                binaryString = sb.toString();
            }
            int cur = judge(binaryString);
            if (cur != 0) {
                if (flag) {
                    if (cur == -1) {
                        cnt++;
                    } else {
                        return false;
                    }
                    if (cnt == need) {
                        flag = false;
                        cnt = 0;
                    }
                } else {
                    if (cur == -1) {
                        return false;
                    } else {
                        need = cur;
                        flag = true;
                    }
                }
            } else {
                if (flag) {
                    return false;
                }
            }
        }
        return !flag;
    }
    public int judge(String str){
        if (str.charAt(0) == '0'){
            return 0;
        }
        if ("10".equals(str.substring(0,2))){
            return -1;
        }
        if ("110".equals(str.substring(0,3))){
            return 1;
        }
        if ("1110".equals(str.substring(0,4))){
            return 2;
        }
        if ("11110".equals(str.substring(0,5))){
            return 3;
        }
        return -1;
    }
}

139. 单词拆分【中等题】

思路:【动态规划】

  1. 遍历字符串每一个字符的后一个位置(这样方便截取子串),设遍历到的下标为i,那么将字符串分为s[0,i-1]和s[i,len)两段,这里只关注前半段,因为随着i的增大后半段会越来越短直至消失。
  2. 对前半段子串,再进行遍历切分,分为s1[0,j-1]和s2[j,i),这里如果s1子串和s2子串均为合法子串,那么整个前半段子串就是合法子串,否则就不是合法子串。
  3. 用dp[i]表示当前字符下标i之前的子串是否为合法子串(即子串是否在字典中存在),由于j是小于i的,那么我们就算dp[i]时,dp[j]必然已被计算过了,于是转移方程可写为:
  4. dp[i] = dp[j] && s2是否合法,s2是否合法可通过枚举所有的小于i的j,判断s[j,i)是否在字典中存在求出。
  5. 边界条件为dp[0]=true,dp[0]表示字符串第一个字符之前的子串,默认为空串,默认是合法的。
  6. 最后返回字符串第len位置之前的子串是否合法即可,即返回dp[len]。

代码:

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> dic = new HashSet<>(wordDict);
        int len = s.length();
        boolean[] dp = new boolean[len+1];
        dp[0] = true;
        for (int i = 1; i <= len; i++) {
            for (int j = 0; j < i; j++) {
                if (dp[j] && dic.contains(s.substring(j,i))){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[len];
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值