首页 > 其他分享 >【DP】LeetCode 剑指 Offer 46. 把数字翻译成字符串

【DP】LeetCode 剑指 Offer 46. 把数字翻译成字符串

时间:2023-03-27 10:47:40浏览次数:54  
标签:string Offer 46 valueOf value int LeetCode dp String

题目链接

剑指 Offer 46. 把数字翻译成字符串

思路

这个问题与 dp 中的经典问题“跳台阶”问题十分类似,在跳台阶问题中我们是选择跳一个台阶或者两个台阶,而在这个问题中我们是选择再统计一个字符还是再统计两个字符。即我们在遍历到第 \(i\) 个字符的时候,可以把它当做前面 \(i-1\) 个字符接上一个字符或者是前面 \(i-2\) 个字符接上两个字符。

举个栗子:

比如有一串数字为 12212
当我们遍历到 1221 时,我们可以看做两种情况:

  • 122 的后面接上了 1
  • 12 的后面接上了 21

所以1221的映射方法应该是122的映射方法数加上12的映射方法数,所以状态转移方程应该包含 \(dp[i]=dp[i-1]+dp[i-2]\)。

这里我们把末尾两字符的值记为 \(value\)。

只不过在跳台阶问题中我们无论怎样都能跳两个台阶,在该问题中需要满足 \(10 \leq value \leq 25\) 才能满足这两个字符能映射到字母,所以取 \(dp[i-2]\) 的值是有条件的。如果不满足条件,说明这种分割方法中的 \(value\) 没法映射到对应字母,即应该舍去 \(dp[i-2]\),此时状态方程变为 \(dp[i]=dp[i-1]\),即此时没法视为在 \(i-2\) 个字符的基础上接两个字符。

举个栗子:

比如有一串数字为 12345
当我们遍历到 1234 时,我们可以看做两种情况:

  • 123 的后面接上了 4
  • 12 的后面接上了 34

但是 34 已经超过了 25,所以它没有映射的字母,需要把这种情况舍去。

综上所述,状态转移方程应该为:

\[dp[i]=\left\{ \begin{aligned} & dp[i-1], & value <10, \\ & dp[i-1] + dp[i-2],& 10 \leq value \leq 25. \\ \end{aligned} \right. \]

代码

dp数组版

class Solution {
    public int translateNum(int num) {
        // dp[i] = dp[i - 1] + dp[i - 2]
        String string = String.valueOf(num);
        if(string.length() == 1){
            return 1;
        }

        int[] dp = new int[string.length()];

        dp[0] = 1;
        dp[1] = Integer.valueOf(string.substring(0, 2)) > 25 ? 1 : 2;
        for(int i = 2; i < string.length(); i++){
            String subString = string.substring(i - 1, i + 1);
            int value = Integer.valueOf(subString);
            if(10 <= value && value <= 25){
                dp[i] = dp[i - 1] + dp[i - 2];
            }else{
                dp[i] = dp[i - 1];
            }
        }
		
        return dp[string.length() - 1];
    }
}

空间优化版

class Solution {
    public int translateNum(int num) {
        // dp[i] = dp[i - 1] + dp[i - 2]
        String string = String.valueOf(num);
        if(string.length() == 1){
            return 1;
        }

        int pre = 1;
        int pre2 = Integer.valueOf(string.substring(0, 2)) > 25 ? 1 : 2;
        int next = pre2;
        for(int i = 2; i < string.length(); i++){
            String subString = string.substring(i - 1, i + 1);
            int value = Integer.valueOf(subString);
            if(10 <= value && value <= 25){
                next = pre + pre2;
            }else{
                next = pre2;
            }
            pre = pre2;
            pre2 = next;
        }

        return next;
    }
}

标签:string,Offer,46,valueOf,value,int,LeetCode,dp,String
From: https://www.cnblogs.com/shixuanliu/p/17260711.html

相关文章

  • 快慢指针-leetcode141-判断链表中是否有环。
    LeetCode#141题目描述:给定一个链表,判断链表中是否有环。如果链表中存在环,则返回true。否则,返回false。进阶:你能用O(1)(即,常量)内存解决此问题吗?示例1:example1......
  • LeetCode 111.二叉树的最小深度
    1.题目给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。示例1:输入:root=[3,9,20,null,null......
  • LeetCode 202 快乐数
    LeetCode202快乐数题目跳转链接具体实现思路如下:实现一个函数getSum,用来计算一个数各个位上的数字的平方和。具体实现就是对这个数进行除十操作和取余操作,对每个位......
  • Leetcode 349. 两个数组的交集
    力扣题目跳转链接代码随想录题解题目要求:给定两个数组nums1和nums2,返回它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。......
  • 【LeetCode动态规划#05】背包问题的理论分析(基于代码随想录的个人理解,多图)
    背包问题问题描述背包问题是一系列问题的统称,具体包括:01背包、完全背包、多重背包、分组背包等(仅需掌握前两种,后面的为竞赛级题目)下面来研究01背包实际上即使是最经典......
  • LeetCode 142.环形链表II
    力扣LeetCode142.环形链表II题目跳转链接解题思路:代码随想录:142.环形链表II从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点,那么当这......
  • LeetCode|1574. 删除最短的子数组使剩余数组有序
    题目链接:1574.删除最短的子数组使剩余数组有序给你一个整数数组arr,请你删除一个子数组(可以为空),使得arr中剩下的元素是非递减的。一个子数组指的是原数组中连续......
  • LeetCode|1032. 字符流
    题目链接:1032.字符流设计一个算法:接收一个字符流,并检查这些字符的后缀是否是字符串数组words中的一个字符串。例如,words=["abc","xyz"]且字符流中逐个依次加入......
  • 【LeetCode动态规划#04】不同的二叉搜索树(找规律,有点像智力题)
    不同的二叉搜索树力扣题目链接(opensnewwindow)给定一个整数n,求以1...n为节点组成的二叉搜索树有多少种?示例:思路题意分析先找一下关系当n=1时,如果元素就......
  • LeetCode199.二叉树的右视图
    1.题目:给定一个二叉树的根节点root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。示例1:输入: [1,2,3,null,5,null,4]输出: [1,3,4]来源:力......