几道动态规划题目

89 阅读1分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

剑指offer49题

题目描述

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

题解

转移方程

image.png 也就是说如果知道索引a,b,c那么就可以得到的当前答案。

a,b,c最开始的值都是为1

那么,a,b,c如何更新呢(什么时候需要更新)?

显然:

只有当dp[i]>=dp[a]*2或者dp[i]>=dp[b]*3或者dp[i]>=dp[c]*5时才需要更新,加1即可。

而dp[i]=min(dp[a]*2,dp[b]*3,dp[c]*5)。

所以不会有“>”的情况,只会有“=”的情况。

public int nthUglyNumber(int n) {
    int a=1,b=1,c=1;
    int dp[]=new int[n+1];
    dp[1]=1;
    for(int i=2; i<=n; i++){
        dp[i]=Math.min(dp[a]*2,Math.min(dp[b]*3,dp[c]*5));
        a=dp[a]*2==dp[i]?a+1:a;
        b=dp[b]*3==dp[i]?b+1:b;
        c=dp[c]*5==dp[i]?c+1:c;
    }
    return dp[n];
}

恢复空格

题目描述

image.png

题解

首先,需要知道朴素的动态规划的做法

dp[i] : 表示前i个字符的最少未识别字符数。

那么dp[i]由两个状态转移而来,一个是sentence[i-1]不与之前的字符串构成字符串,此时dp[i]=dp[i-1]+1,而与之前的字符串构成字符串的话,那么就要找到所有满足条件的字符串的第一个字符下标j,此时dp[i]=dp[j]计为array,然后遍历array,用min(dp[i],dp[j])来更新就好。

这里为了更快地将array早出来,使用字典树这个数据结构进行优化。

class Solution {
    class tree{
        tree[] child=new tree[26];
        boolean end;
        char value;
        tree(char value){
            this.value=value;
        }
        tree(){

        }
    }
    public int respace(String[] dictionary, String sentence) {
        tree root=new tree();
        for (String s : dictionary) {
            tree occur=root;
            //这里倒序存储使得其有公共后缀。
            for(int i=s.length()-1; i>=0; i--){
                if(occur.child[s.charAt(i)-'a']==null)occur.child[s.charAt(i)-'a']=new tree(s.charAt(i));
                occur=occur.child[s.charAt(i)-'a'];
                if(i==0)occur.end=true;
            }
        }
        //dp[i]表示前i个元素的字符不可识别个数
        int[] dp=new int[sentence.length()+1];
        dp[0]=0;
        for(int i=1; i<dp.length; i++){
            dp[i]=dp[i-1]+1;
            //此时末尾是i-1
            List<Integer> list=getList(root,i-1,sentence);
            for (Integer integer : list) {
                dp[i]=Math.min(dp[i],dp[integer]);
            }
        }
        return dp[dp.length-1];
    }
    //将所有以pos结尾的满足条件的字符串找到,并存储其首字符下标。
    List<Integer> getList(tree root,int pos,String sentence){
            List<Integer> result=new ArrayList<>();
            tree occur=root;
            for(int i=pos; i>=0; i--){
                if(occur.child[sentence.charAt(i)-'a']==null)break;
                occur=occur.child[sentence.charAt(i)-'a'];
                if(occur.end)result.add(i);
            }
            return result;
    }
}