每日一题算法: 2020年7月9日 面试题 17.13. 恢复空格 respace

2020年7月9日 面试题 17.13. 恢复空格 respace

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oe6UGXbJ-1594303115135)(C:%5CUsers%5CAdmin%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20200709193647677.png)]

默认格式:

class Solution {
    public int respace(String[] dictionary, String sentence) {

    }
}

解题思路:

前几天写过一个差不多的,拆分单词。如果只是做判断其实很简单,遍历数组,每个单词去字典里找是否有以该单词开头的,如果有的话就继续,没有的话记录为无法匹配,然后继续算,找出所有的无法匹配的。

实际上,难点是存在于如何控制条件而减少匹配的次数,比如,我们记下前n项中最短的未匹配数,然后计算后m向中的未匹配字符。

当计算到just的时候,判断出前面最少的未匹配字符有两种,一种是6个另一种是4个,把4个记录在数组中,如果计算到just的时候计算的未匹配比4要大,直接放弃不再计算。
在这里插入图片描述

上面计算的是just的t的位置上的最小值,而不是t之前的最小值,比如下面,到达just的s这个位置最少未匹配字符是5,比t的最小未匹配字符数小,而实际上这个s位置上的最少未匹配字符任然是有意义的。

在这里插入图片描述

代码部分:

初版:

在这里插入图片描述

    int[] res;
    public int respace(String[] dictionary, String sentence) {

        int max=Integer.MAX_VALUE;
        res=new int[sentence.length()];
        //初始化数组
        for (int i=0;i<res.length;i++){
            res[i]=max;
        }

        respace2(dictionary,sentence,0 );

        return res[res.length-1];

    }
    public void respace2(String[] dictionary, String sentence,int index){

        //从第一个字符开始遍历
        for (int i=index;i<sentence.length();i++){

            //看一下第一个字符是否存在直接匹配的单词,看一下有几个能匹配的
            for (int j=0;j<dictionary.length;j++){
                if(matchWord(dictionary[j],sentence ,i)){
                    if (i==0){
                        res[i+dictionary[j].length()-1]=0;
                    }
                    else if (res[i+dictionary[j].length()-1]>=res[i-1])
                        res[i+dictionary[j].length()-1]=res[i-1];
                    else
                        return;

                    respace2(dictionary,sentence ,dictionary[j].length()+i);

                }
            }

            //判断当前字符的值的状态,是否是当前位置的最优值,如果不是,直接返回
            if (i-1>=0&&res[i]>res[i-1]+1){
                res[i]=res[i-1]+1;
            }else if (i==0){
                res[0]=1;
            }else
                return;
        }

    }
    public boolean matchWord(String word,String sentence,int index){
        int i=0;
 for (;i+index<sentence.length()&&i<word.length()&&sentence.charAt(i+index)==word.charAt(i);i++);

        if (i==word.length()){
            return true;
        }else
            return false;

    }

开始测试是什么原因:

@Test
public void test(){
    String[] dictionary={"tt","ttt","t","t"};
    String sentence="tttttt";
    System.out.println(respace(dictionary,sentence ));
}

在这里插入图片描述

这么短都需要4ms,肯定存在问题。

修改后2.0版本

增加了基础状态的判断,字符串是否为空等。

增加了是否需要寻找匹配单词的判断,如果找到了匹配的单词,但是匹配后的位置上的值已经比当前处理的值要小了,那么就没有比较的必要了。
在这里插入图片描述

实际上可以更优化,因为我的算法很多部分都写得很粗糙。今天我就不优化了。

int[] res;
public int respace(String[] dictionary, String sentence) {

    if (dictionary.length==0)
        return sentence.length();
    if (sentence.equals(""))
        return 0;

    int max=Integer.MAX_VALUE;
    res=new int[sentence.length()];
    //初始化数组
    for (int i=0;i<res.length;i++){
        res[i]=max;
    }

    respace2(dictionary,sentence,0 );

    return res[res.length-1];

}
public void respace2(String[] dictionary, String sentence,int index){

    //从第一个字符开始遍历
    for (int i=index;i<sentence.length();i++){

        //看一下第一个字符是否存在直接匹配的单词,看一下有几个能匹配的
        for (int j=0;j<dictionary.length;j++){

            if(matchWord(dictionary[j],sentence ,i)){
                if (i==0){
                    res[i+dictionary[j].length()-1]=0;
                }
                else if (res[i+dictionary[j].length()-1]>=res[i-1])
                    res[i+dictionary[j].length()-1]=res[i-1];
                else
                    return;

                respace2(dictionary,sentence ,dictionary[j].length()+i);

            }
        }

        //判断当前字符的值的状态,是否是当前位置的最优值,如果不是,直接返回
        if (i-1>=0&&res[i]>res[i-1]+1){
            res[i]=res[i-1]+1;
        }else if (i==0){
            res[0]=1;
        }else
            return;
    }

}
public boolean matchWord(String word,String sentence,int index){


    //大于0,长度符合的情况下,如果字符的处理后的位置的值和前一个一样,那么比较就没有意义不比较,直接返回不匹配
    if (index!=0&&index+word.length()<res.length&&res[index+word.length()-1]<=res[index-1]){
        return false;
    }

    int i=0;
    for (;i+index<sentence.length()&&i<word.length()&&sentence.charAt(i+index)==word.charAt(i);i++);

    if (i==word.length()){
        return true;
    }else
        return false;

}
©️2020 CSDN 皮肤主题: 游动-白 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值