46. 把数字翻译成字符串【难】

打印 上一主题 下一主题

主题 1839|帖子 1839|积分 5517

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9846.%20%E6%8A%8A%E6%95%B0%E5%AD%97%E7%BF%BB%E8%AF%91%E6%88%90%E5%AD%97%E7%AC%A6%E4%B8%B2/README.md


  面试题 46. 把数字翻译成字符串

标题描述

  给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来盘算一个数字有多少种不同的翻译方法。
 
示例 1:
  1. <strong>输入:</strong> 12258
  2. <strong>输出:</strong> 5
  3. <strong>解释:</strong> 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
复制代码
 
提示:


  • 0 <= num < 231
  解法

  方法一:记忆化搜刮

我们先将数字 num 转为字符串                                    s                              s                  s,字符串                                    s                              s                  s 的长度记为                                    n                              n                  n。
然后我们设计一个函数                                         d                            f                            s                            (                            i                            )                                  dfs(i)                     dfs(i),表现从第                                         i                                  i                     i 位数字开始的不同翻译的数目。那么答案就是                                    d                         f                         s                         (                         0                         )                              dfs(0)                  dfs(0)。
函数                                    d                         f                         s                         (                         i                         )                              dfs(i)                  dfs(i) 的盘算如下:


  • 如果                                         i                            ≥                            n                            −                            1                                  i \ge n - 1                     i≥n−1,分析已经翻译到最后一个数字,只有一种翻译方法,返回                                         1                                  1                     1;
  • 否则,我们可以选择翻译第                                         i                                  i                     i 位数字,此时翻译方法数目为                                         d                            f                            s                            (                            i                            +                            1                            )                                  dfs(i + 1)                     dfs(i+1);如果第                                              i                                      i                        i 位数字和第                                              i                               +                               1                                      i + 1                        i+1 位数字可以构成一个有效的字符(即                                              s                               [                               i                               ]                               =                               =                               1                                      s == 1                        s==1 或者 (                                             s                               [                               i                               ]                               =                               =                               2                                      s == 2                        s==2 且                                              s                               [                               i                               +                               1                               ]                               <                               6                                      s[i + 1] \lt 6                        s[i+1]<6)),那么我们还可以选择翻译第                                         i                                  i                     i 和第                                         i                            +                            1                                  i + 1                     i+1 位数字,此时翻译方法数目为                                         d                            f                            s                            (                            i                            +                            2                            )                                  dfs(i + 2)                     dfs(i+2)。因此                                         d                            f                            s                            (                            i                            )                            =                            d                            f                            s                            (                            i                            +                            1                            )                            +                            d                            f                            s                            (                            i                            +                            2                            )                                  dfs(i) = dfs(i+1) + dfs(i+2)                     dfs(i)=dfs(i+1)+dfs(i+2)。
过程中我们可以使用记忆化搜刮,将已经盘算过的                                    d                         f                         s                         (                         i                         )                              dfs(i)                  dfs(i) 的值存储起来,避免重复盘算。
时间复杂度                                    O                         (                         log                         ⁡                         n                         u                         m                         )                              O(\log num)                  O(lognum),空间复杂度                                    O                         (                         log                         ⁡                         n                         u                         m                         )                              O(\log num)                  O(lognum)。此中                                    n                         u                         m                              num                  num 为给定的数字。
  Python3

  1. class Solution:
  2.     def translateNum(self, num: int) -> int:
  3.         @cache
  4.         def dfs(i):
  5.             if i >= n - 1: #第i-1位数字往后只有一种翻译方式
  6.                 return 1
  7.                
  8.             ans = dfs(i + 1)
  9.             if s[i] == "1" or (s[i] == "2" and s[i + 1] < "6"):#核心:当有两位数字且不大于26时,就会出现两种翻译方式,从而翻译种数dfs(i)=dfs(i+1)+dfs(i+1)
  10.                 ans += dfs(i + 2)
  11.             return ans
  12.         s = str(num)
  13.         n = len(s)
  14.         return dfs(0)
复制代码
Java

  1. class Solution {
  2.     private int n;
  3.     private char[] s;
  4.     private Integer[] f;
  5.     public int translateNum(int num) {
  6.         s = String.valueOf(num).toCharArray();
  7.         n = s.length;
  8.         f = new Integer[n];
  9.         return dfs(0);
  10.     }
  11.     private int dfs(int i) {
  12.         if (i >= n - 1) {
  13.             return 1;
  14.         }
  15.         if (f[i] != null) {
  16.             return f[i];
  17.         }
  18.         int ans = dfs(i + 1);
  19.         if (s[i] == '1' || (s[i] == '2' && s[i + 1] < '6')) {
  20.             ans += dfs(i + 2);
  21.         }
  22.         return f[i] = ans;
  23.     }
  24. }
复制代码
C++

  1. class Solution {
  2. public:
  3.     int translateNum(int num) {
  4.         string s = to_string(num);
  5.         int n = s.size();
  6.         int f[12]{};
  7.         function<int(int)> dfs = [&](int i) -> int {
  8.             if (i >= n - 1) {
  9.                 return 1;
  10.             }
  11.             if (f[i]) {
  12.                 return f[i];
  13.             }
  14.             int ans = dfs(i + 1);
  15.             if (s[i] == '1' || (s[i] == '2' && s[i + 1] < '6')) {
  16.                 ans += dfs(i + 2);
  17.             }
  18.             return f[i] = ans;
  19.         };
  20.         return dfs(0);
  21.     }
  22. };
复制代码
Go

  1. func translateNum(num int) int {
  2.         s := strconv.Itoa(num)
  3.         n := len(s)
  4.         f := [12]int{}
  5.         var dfs func(int) int
  6.         dfs = func(i int) int {
  7.                 if i >= n-1 {
  8.                         return 1
  9.                 }
  10.                 if f[i] != 0 {
  11.                         return f[i]
  12.                 }
  13.                 ans := dfs(i + 1)
  14.                 if s[i] == '1' || (s[i] == '2' && s[i+1] < '6') {
  15.                         ans += dfs(i + 2)
  16.                 }
  17.                 f[i] = ans
  18.                 return ans
  19.         }
  20.         return dfs(0)
  21. }
复制代码
TypeScript

  1. function translateNum(num: number): number {
  2.     const s = num.toString();
  3.     const n = s.length;
  4.     const f = new Array(n).fill(0);
  5.     const dfs = (i: number): number => {
  6.         if (i >= n - 1) {
  7.             return 1;
  8.         }
  9.         if (f[i]) {
  10.             return f[i];
  11.         }
  12.         let ans = dfs(i + 1);
  13.         if (s[i] === '1' || (s[i] === '2' && s[i + 1] < '6')) {
  14.             ans += dfs(i + 2);
  15.         }
  16.         f[i] = ans;
  17.         return ans;
  18.     };
  19.     return dfs(0);
  20. }
复制代码
Rust

  1. impl Solution {
  2.     pub fn translate_num(num: i32) -> i32 {
  3.         let mut a = 1;
  4.         let mut b = 1;
  5.         let str = num.to_string();
  6.         for i in 0..str.len() - 1 {
  7.             let c = a + b;
  8.             a = b;
  9.             let num = str[i..i + 2].parse::<i32>().unwrap();
  10.             if num >= 10 && num < 26 {
  11.                 b = c;
  12.             }
  13.         }
  14.         b
  15.     }
  16. }
复制代码
JavaScript

  1. /**
  2. * @param {number} num
  3. * @return {number}
  4. */
  5. var translateNum = function (num) {
  6.     const s = num.toString();
  7.     const n = s.length;
  8.     const f = new Array(n).fill(0);
  9.     const dfs = i => {
  10.         if (i >= n - 1) {
  11.             return 1;
  12.         }
  13.         if (f[i]) {
  14.             return f[i];
  15.         }
  16.         let ans = dfs(i + 1);
  17.         if (s[i] === '1' || (s[i] === '2' && s[i + 1] < '6')) {
  18.             ans += dfs(i + 2);
  19.         }
  20.         f[i] = ans;
  21.         return ans;
  22.     };
  23.     return dfs(0);
  24. };
复制代码
C#

  1. public class Solution {
  2.     public int TranslateNum(int num) {
  3.         var s = num.ToString();
  4.         int n = s.Length;
  5.         int a = 1, b = 1;
  6.         for (int i = 1; i < n; ++i) {
  7.             int c = b;
  8.             if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] < '6')) {
  9.                 c += a;
  10.             }
  11.             a = b;
  12.             b = c;
  13.         }
  14.         return b;
  15.     }
  16. }
复制代码
Swift

  1. class Solution {
  2.     private var n: Int = 0
  3.     private var s: [Character] = []
  4.     private var memo: [Int?] = []
  5.     func translateNum(_ num: Int) -> Int {
  6.         s = Array(String(num))
  7.         n = s.count
  8.         memo = [Int?](repeating: nil, count: n)
  9.         return dfs(0)
  10.     }
  11.     private func dfs(_ i: Int) -> Int {
  12.         if i >= n - 1 {
  13.             return 1
  14.         }
  15.         if let cachedResult = memo[i] {
  16.             return cachedResult
  17.         }
  18.         var ans = dfs(i + 1)
  19.         if s[i] == "1" || (s[i] == "2" && s[i + 1] < "6") {
  20.             ans += dfs(i + 2)
  21.         }
  22.         memo[i] = ans
  23.         return ans
  24.     }
  25. }
复制代码
   方法二:动态规划

我们可以将方法一中的记忆化搜刮改为动态规划。
定义                                         f                            [                            i                            ]                                  f                     f 表现前                                         i                                  i                     i 个数字的不同翻译的数目,那么答案就是                                         f                            [                            n                            ]                                  f[n]                     f[n]。初始化                                         f                            [                            0                            ]                            =                            1                                  f[0] = 1                     f[0]=1,                                         f                            [                            1                            ]                            =                            1                                  f[1] = 1                     f[1]=1。
我们可以从前今后盘算                                    f                         [                         i                         ]                              f                  f 的值,对于每个                                    i                              i                  i,我们可以选择翻译第                                    i                              i                  i 个数字,此时翻译方法数目为                                    f                         [                         i                         −                         1                         ]                              f[i - 1]                  f[i−1];如果第                                    i                         −                         1                              i-1                  i−1 个数字和第                                    i                              i                  i 个数字可以构成一个有效的字符(即                                    s                         [                         i                         −                         1                         ]                         =                         =                         1                              s[i - 1] == 1                  s[i−1]==1 或者                                    s                         [                         i                         −                         1                         ]                         =                         =                         2                              s[i - 1] == 2                  s[i−1]==2 且                                    s                         [                         i                         ]                         <                         6                              s \lt 6                  s<6),那么我们还可以选择翻译第                                    i                         −                         1                              i - 1                  i−1 和第                                    i                              i                  i 个数字,此时翻译方法数目为                                    f                         [                         i                         −                         2                         ]                              f[i - 2]                  f[i−2]。因此                                    f                         [                         i                         ]                         =                         f                         [                         i                         −                         1                         ]                         +                         f                         [                         i                         −                         2                         ]                              f = f[i-1] + f[i-2]                  f=f[i−1]+f[i−2]。
由于                                    f                         [                         i                         ]                              f                  f 只与                                    f                         [                         i                         −                         1                         ]                              f[i - 1]                  f[i−1] 和                                    f                         [                         i                         −                         2                         ]                              f[i - 2]                  f[i−2] 有关,因此我们可以只用两个变量来存储                                    f                         [                         i                         −                         1                         ]                              f[i - 1]                  f[i−1] 和                                    f                         [                         i                         −                         2                         ]                              f[i - 2]                  f[i−2] 的值,从而省去数组                                    f                              f                  f 的空间。
时间复杂度                                    O                         (                         log                         ⁡                         n                         u                         m                         )                              O(\log num)                  O(lognum),空间复杂度                                    O                         (                         log                         ⁡                         n                         u                         m                         )                              O(\log num)                  O(lognum)。此中                                    n                         u                         m                              num                  num 为给定的数字。
  Python3

  1. class Solution:
  2.     def translateNum(self, num: int) -> int:
  3.         s = str(num)
  4.         n = len(s)
  5.         a = b = 1
  6.         for i in range(2, n+1):
  7.             c = b
  8.             if s[i - 2] == '1' or (s[i - 2] == '2' and s[i-1] < '6'):#注意:第i个数字对应第i-1位
  9.                 c += a
  10.             a, b = b, c
  11.         return b
复制代码
Java

  1. class Solution {
  2.     public int translateNum(int num) {
  3.         char[] s = String.valueOf(num).toCharArray();
  4.         int n = s.length;
  5.         int a = 1, b = 1;
  6.         for (int i = 1; i < n; ++i) {
  7.             int c = b;
  8.             if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] < '6')) {
  9.                 c += a;
  10.             }
  11.             a = b;
  12.             b = c;
  13.         }
  14.         return b;
  15.     }
  16. }
复制代码
C++

  1. class Solution {
  2. public:
  3.     int translateNum(int num) {
  4.         string s = to_string(num);
  5.         int n = s.size();
  6.         int a = 1, b = 1;
  7.         for (int i = 1; i < n; ++i) {
  8.             int c = b;
  9.             if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] < '6')) {
  10.                 c += a;
  11.             }
  12.             a = b;
  13.             b = c;
  14.         }
  15.         return b;
  16.     }
  17. };
复制代码
Go

  1. func translateNum(num int) int {
  2.         s := strconv.Itoa(num)
  3.         n := len(s)
  4.         a, b := 1, 1
  5.         for i := 1; i < n; i++ {
  6.                 c := b
  7.                 if s[i-1] == '1' || (s[i-1] == '2' && s[i] < '6') {
  8.                         c += a
  9.                 }
  10.                 a, b = b, c
  11.         }
  12.         return b
  13. }
复制代码
TypeScript

  1. function translateNum(num: number): number {
  2.     const s = num.toString();
  3.     const n = s.length;
  4.     let a = 1;
  5.     let b = 1;
  6.     for (let i = 1; i < n; ++i) {
  7.         let c = b;
  8.         if (s[i - 1] === '1' || (s[i - 1] === '2' && s[i] < '6')) {
  9.             c += a;
  10.         }
  11.         a = b;
  12.         b = c;
  13.     }
  14.     return b;
  15. }
复制代码
Rust

  1. impl Solution {
  2.     fn dfs(s: &String, i: usize, res: &mut i32) {
  3.         if i >= s.len() {
  4.             return;
  5.         }
  6.         let val = s[i - 1..=i].parse::<i32>().unwrap();
  7.         if val >= 10 && val <= 25 {
  8.             *res += 1;
  9.             Self::dfs(s, i + 2, res);
  10.         }
  11.         Self::dfs(s, i + 1, res);
  12.     }
  13.     pub fn translate_num(num: i32) -> i32 {
  14.         let s = num.to_string();
  15.         let mut res = 1;
  16.         Self::dfs(&s, 1, &mut res);
  17.         res
  18.     }
  19. }
复制代码
JavaScript

  1. /**
  2. * @param {number} num
  3. * @return {number}
  4. */
  5. var translateNum = function (num) {
  6.     const s = num.toString();
  7.     const n = s.length;
  8.     let a = 1;
  9.     let b = 1;
  10.     for (let i = 1; i < n; ++i) {
  11.         let c = b;
  12.         if (s[i - 1] === '1' || (s[i - 1] === '2' && s[i] < '6')) {
  13.             c += a;
  14.         }
  15.         a = b;
  16.         b = c;
  17.     }
  18.     return b;
  19. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

河曲智叟

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表