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

题目链接:剑指 Offer 46. 把数字翻译成字符串

方法:回溯、动态规划

解题思路

  1. 动态规划是回溯中“归”的过程;
  2. 思考回溯:
    (1)将\(num\)转换为字符串\(s\)
    (2)对于当前位置\(i\),可能有两种操作,将\(s[i] => 字符\) 或 将\(s[i, i + 1] => 字符\),即\(dfs(i) = dfs(i + 1) + dfs(i + 2)\)
    (3)\(dfs(i + 1)\)对应将\(s[i] => 字符\)\(dfs(i + 2)\)对应将\(s[i, i + 1] => 字符\)
  3. 转换为动态规划
    考虑回溯“归”的过程:对于\(当前dp值(dfs(i))\)\(前一个dp值(dfs(i + 1))\)\(前两个dp值(dfs(i + 2))\)决定,且\(i\)\(n-1\)递减到\(0\)

代码

回溯写法

class Solution {
public:
    int translateNum(int num) {
        string s = to_string(num);
        int n = s.length();
        vector<int> cache(n);
        function<int(int)> dfs = [&](int i) -> int {
            if (i == n) return 1; // 翻译为合法字符串
            if (cache[i] != 0) return cache[i];
            int res = dfs(i + 1);
            if (s[i] != '0' && i + 1 < n) {
                int idx = stoi(s.substr(i, 2));
                if (idx < 26) res += dfs(i + 2);
            }
            cache[i] = res;
            return res;
        };
        return dfs(0);
    }
};

动态规划写法

class Solution {
public:
    int translateNum(int num) {
        string s = to_string(num);
        int n = s.length(), last_1 = 1, last_2 = 1, dp = 1; // last_1表示前一个dp值,last_2表示前两个的dp值
        for (int i = n - 1; i >= 0; i -- ) {
            dp = last_1;
            if (i + 1 < n && s[i] != '0' && stoi(s.substr(i, 2)) < 26) {
                dp += last_2;
            }
            last_2 = last_1, last_1 = dp; // 更新变量
        }
        return dp;
    }
};

复杂度分析

时间复杂度:回溯为\(O(n)\)\(dp\)\(O(n)\)
空间复杂度:回溯为\(O(n)\)\(dp\)\(O(1)\)

posted @ 2023-04-09 00:05  lixycc  阅读(21)  评论(0)    收藏  举报