【LeetCode: 1416. 恢复数组 | 暴力递归=>记忆化搜索=>动态规划 】

在这里插入图片描述

🚀 算法题 🚀

🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯

🚀 算法题 🚀

在这里插入图片描述

🚗 知识回顾

该题和我们之前的题目在求解的思路上相似之处,感兴趣的同学可以学习一下相关的内容。

🚩 题目链接

⛲ 题目描述

某个程序本来应该输出一个整数数组。但是这个程序忘记输出空格了以致输出了一个数字字符串,我们所知道的信息只有:数组中所有整数都在 [1, k] 之间,且数组中的数字都没有前导 0 。

给你字符串 s 和整数 k 。可能会有多种不同的数组恢复结果。

按照上述程序,请你返回所有可能输出字符串 s 的数组方案数。

由于数组方案数可能会很大,请你返回它对 10^9 + 7 取余 后的结果。

示例 1:

输入:s = “1000”, k = 10000
输出:1
解释:唯一一种可能的数组方案是 [1000]
示例 2:

输入:s = “1000”, k = 10
输出:0
解释:不存在任何数组方案满足所有整数都 >= 1 且 <= 10 同时输出结果为 s 。
示例 3:

输入:s = “1317”, k = 2000
输出:8
解释:可行的数组方案为 [1317],[131,7],[13,17],[1,317],[13,1,7],[1,31,7],[1,3,17],[1,3,1,7]
示例 4:

输入:s = “2020”, k = 30
输出:1
解释:唯一可能的数组方案是 [20,20] 。 [2020] 不是可行的数组方案,原因是 2020 > 30 。 [2,020] 也不是可行的数组方案,因为 020 含有前导 0 。
示例 5:

输入:s = “1234567890”, k = 90
输出:34

提示:

1 <= s.length <= 10^5.
s 只包含数字且不包含前导 0 。
1 <= k <= 10^9.

🌟 求解思路&实现代码&运行结果


⚡ 暴力递归

🥦 求解思路
  1. 该题目让我们求解的是将s进行一个划分,每一个划分的部分都小于等于k的总体方案数。
  2. 总体求解思路还是动态规划,为什么呢?因为我们想要求解的是从0位置开始,到s的最后一个位置结束,满足每个部分小于等于k的总体方案数目。如果说我们此时划分了0-cur位置,那么从cur-最后一个结束位置还需要重复这个过程,所以说,该过程是存在重复子问题的,我们可以通过动态规划来进行一个求解。
  3. 首先,我们还是设计一个递归函数,递归函数的含义是从index位置开始进行划分,找到所有满足的方案数。
🥦 实现代码
class Solution {

    private int mod=(int) 1e9 + 7;

    public int numberOfArrays(String s, int k) {
        return (int)(process(0,s,k)%mod);
    }

    public long process(int index,String s,int k){
        if(index>=s.length()){
            return 1;
        }
        long res=0;
        for(int i=index;i<s.length();i++){
            long sum=0;
            for(int j=index;j<i+1;j++){
                sum=sum*10+s.charAt(j)-'0';
            }
            if(s.substring(index,i+1).charAt(0)!='0'&&sum<=k&&sum>=1){
                res+=process(i+1,s,k)%mod;
            }
        }
        return res%mod;
    }
}
🥦 运行结果

时间超限了,不要紧哦,我还有锦囊妙计!

在这里插入图片描述


⚡ 记忆化搜索

🥦 求解思路
  1. 根据我们递归的分析,在递归的过程中会产生重复的子过程,所以我们想到了加一个缓存表,也就是我们的记忆化搜索。
  2. 因为题目给定我们的k的限制条件是k≤10^9 ,所以我们最多只要枚举 10个数字就行了,这个也是我们优化的一个点,否则时间还是会超限的。
🥦 实现代码
class Solution {

    private int mod=(int) 1e9 + 7;
    private long[] dp;

    public int numberOfArrays(String s, int k) {
        dp=new long[s.length()];
        Arrays.fill(dp,-1);
        return process(0,s,k)%mod;
    }

    public int process(int index,String s,int k){
        if(index>=s.length()){
            return 1;
        }
        if(dp[index]!=-1) return (int)(dp[index]);
        long res=0;
        long sum=0,base=10;
        for(int i=index;i<s.length()&&i-index<=10;i++){
            if(s.substring(index,i+1).charAt(0)=='0') continue;
            sum=sum*base+s.charAt(i)-'0';
            if(sum<=k&&sum>=1){
                res+=process(i+1,s,k)%mod;
            }
        }
        return (int)(dp[index]=res%mod);
    }
}
🥦 运行结果

在这里插入图片描述


⚡ 动态规划

🥦 求解思路
  1. 按照我们之前递归和记忆化搜索的思路,通过动态规划实现出来。
🥦 实现代码
class Solution {

    private int mod=(int) 1e9 + 7;
    private long[] dp;

    public int numberOfArrays(String s, int k) {
        int n=s.length();
        dp=new long[n+1];
        dp[n]=1;
        for(int index=n-1;index>=0;index--){
            long res=0;
            long sum=0,base=10;
            for(int i=index;i<s.length()&&i-index<=10;i++){
                if(s.substring(index,i+1).charAt(0)=='0') continue;
                sum=sum*base+s.charAt(i)-'0';
                if(sum<=k&&sum>=1){
                    res+=dp[i+1]%mod;
                }
            }
            dp[index]=res%mod;
        }
        return (int)(dp[0]%mod);
    }
}
🥦 运行结果

在这里插入图片描述


💬 共勉

最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉!

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值