Leetcode刷题之旅(每日一题)--面试题 17.13. 恢复空格

题目描述:
在这里插入图片描述
思路:这道题和139.单词拆分 有些类似。但是动态规划的转移方程不同。要注意的几点:1.不能用boolean的动态规划矩阵。2.HashSet能丢入容器构造但是不能丢入单纯的数组。3.题目要求返回的未识别字数的数量最小,所以当当前单词包含的时候要进行判定这样包含是否返回的是最少的未识别字符数。

class Solution {
    public int respace(String[] dictionary, String sentence) {
        HashSet<String> hashSet=new HashSet();
        int len=sentence.length();
        int count=0;
        int[] result=new int[len+1];
        for(int i=0;i<dictionary.length;i++){
            hashSet.add(dictionary[i]);
        }
        for(int i=1;i<=len;i++){
            result[i]=result[i-1]+1;
            for(int j=0;j<i;j++){
                if(hashSet.contains(sentence.substring(j,i))){
                    result[i]=Math.min(result[i],result[j]);
                }
            }
        }
        return result[len];
    }
}

执行结果:
在这里插入图片描述
时间复杂度很高,该如何改进?官方题解2用了字符串Hash表。(个人理解是不存放字符串,而将字符串转换为数字hashcode存放便于查找)
官方代码

class Solution {
    static final long P = Integer.MAX_VALUE;
    static final long BASE = 41;

    public int respace(String[] dictionary, String sentence) {
        Set<Long> hashValues = new HashSet<Long>();
        for (String word : dictionary) {
            hashValues.add(getHash(word));
        }

        int[] f = new int[sentence.length() + 1];
        Arrays.fill(f, sentence.length());

        f[0] = 0;
        for (int i = 1; i <= sentence.length(); ++i) {
            f[i] = f[i - 1] + 1;
            long hashValue = 0;
            for (int j = i; j >= 1; --j) {
                int t = sentence.charAt(j - 1) - 'a' + 1;
                hashValue = (hashValue * BASE + t) % P;
                if (hashValues.contains(hashValue)) {
                    f[i] = Math.min(f[i], f[j - 1]);
                }
            }
        }

        return f[sentence.length()];
    }

    public long getHash(String s) {
        long hashValue = 0;
        for (int i = s.length() - 1; i >= 0; --i) {
            hashValue = (hashValue * BASE + s.charAt(i) - 'a' + 1) % P;
        }
        return hashValue;
    }
}

另外,官方给出的最优解法为应用字典树
在这里插入图片描述
在这里插入图片描述
代码:

class Solution {
    public int respace(String[] dictionary, String sentence) {
        int n = sentence.length();

        Trie root = new Trie();
        for (String word: dictionary) {
            root.insert(word);
        }

        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 1; i <= n; ++i) {
            dp[i] = dp[i - 1] + 1;

            Trie curPos = root;
            for (int j = i; j >= 1; --j) {
                int t = sentence.charAt(j - 1) - 'a';
                if (curPos.next[t] == null) {
                    break;
                } else if (curPos.next[t].isEnd) {
                    dp[i] = Math.min(dp[i], dp[j - 1]);
                }
                if (dp[i] == 0) {
                    break;
                }
                curPos = curPos.next[t];
            }
        }
        return dp[n];
    }
}

class Trie {
    public Trie[] next;
    public boolean isEnd;

    public Trie() {
        next = new Trie[26];
        isEnd = false;
    }

    public void insert(String s) {
        Trie curPos = this;

        for (int i = s.length() - 1; i >= 0; --i) {
            int t = s.charAt(i) - 'a';
            if (curPos.next[t] == null) {
                curPos.next[t] = new Trie();
            }
            curPos = curPos.next[t];
        }
        curPos.isEnd = true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值