力扣 C++|一题多解之动态规划专题(2)

news2024/11/14 10:37:05

fe34a1c92c5f489689fd991ff5e0f559.png

动态规划

Dynamic Programming

简写为 DP,是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果。

动态规划算法的基本步骤包括:

  1. 确定状态:确定需要求解的状态,并将其表示为变量。
  2. 确定状态转移方程:根据问题的特定约束条件和目标函数,确定状态之间的转移关系,并将其表示为数学公式。
  3. 初始化:为初始状态赋初值,并将其表示为初始条件。
  4. 递推计算:根据状态转移方程,使用循环依次计算各个状态的解,并将其保存在数组或表中。
  5. 求解最终结果:根据问题的目标,从计算得到的解中得出最终结果。

动态规划算法可以用于解决各种问题,例如最短路径问题、背包问题、最长公共子序列问题等。在实现动态规划算法时,需要根据具体问题的特点进行设计和调整,以确保算法的正确性和效率。

适用条件

任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。

最优化原理(最优子结构性质)

最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质 [8] 。

无后效性

将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性 [8] 。

子问题的重叠性

动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。

真题举例(2)

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
        1.  1 阶 + 1 阶
        2.  2 阶

示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
        1.  1 阶 + 1 阶 + 1 阶
        2.  1 阶 + 2 阶
        3.  2 阶 + 1 阶

代码1: 

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int climbStairs(int n)
    {
        if (n == 1)
        {
            return 1;
        }
        int first = 1;
        int second = 2;
        for (int i = 3; i <= n; i++)
        {
            int third = first + second;
            first = second;
            second = third;
        }
        return second;
    }
};

int main()
{
	Solution s;

	cout << s.climbStairs(2) << endl;
	cout << s.climbStairs(3) << endl;
	
	return 0;
} 

代码2:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int climbStairs(int n)
    {
        vector<int> res(n + 1, 0);
        res[1] = 1;
        res[2] = 2;
        for (int i = 3; i <= n; i++)
            res[i] = res[i - 1] + res[i - 2];
        return res[n];
    }
};

int main()
{
	Solution s;

	cout << s.climbStairs(2) << endl;
	cout << s.climbStairs(3) << endl;
	
	return 0;
} 

代码3:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int climbStairs(int n)
    {
        vector<int> s;
        s.push_back(1);
        s.push_back(2);
        if (n == 1)
            return 1;
        if (n == 2)
            return 2;
        for (int i = 2; i < n; i++)
        {
            s.push_back(s[i - 1] + s[i - 2]);
        }
        return s[n - 1];
    }
};

int main()
{
	Solution s;

	cout << s.climbStairs(2) << endl;
	cout << s.climbStairs(3) << endl;
	
	return 0;
} 

72. 编辑距离

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:horse -> rorse (将 'h' 替换为 'r')rorse -> rose (删除 'r')rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:intention -> inention (删除 't')inention -> enention (将 'i' 替换为 'e')enention -> exention (将 'n' 替换为 'x')exention -> exection (将 'n' 替换为 'c')exection -> execution (插入 'u')

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1 和 word2 由小写英文字母组成

代码1:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int minDistance(string word1, string word2)
    {
        int m = word1.size(), n = word2.size();

        if (m == 0)
            return n;
        if (n == 0)
            return m;

        int dp[m][n];
        bool w1 = false, w2 = false;
        if (word1[0] == word2[0])
        {
            w1 = true;
            w2 = true;
            dp[0][0] = 0;
        }
        else
            dp[0][0] = 1;
        for (int i = 1; i < m; i++)
        {
            if (!w1 && word1[i] == word2[0])
            {
                w1 = true;
                dp[i][0] = dp[i - 1][0];
            }
            else
                dp[i][0] = dp[i - 1][0] + 1;
        }
        for (int j = 1; j < n; j++)
        {
            if (!w2 && word1[0] == word2[j])
            {
                w2 = true;
                dp[0][j] = dp[0][j - 1];
            }
            else
                dp[0][j] = dp[0][j - 1] + 1;
        }

        for (int i = 1; i < m; i++)
            for (int j = 1; j < n; j++)
                if (word1[i] == word2[j])
                    dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]) + 1, dp[i - 1][j - 1]);
                else
                    dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
        return dp[m - 1][n - 1];
    }
};

int main()
{
	Solution s;
	string word1 = "horse", word2 = "ros";
	cout << s.minDistance(word1, word2) << endl;
	
	word1 = "intention", word2 = "execution";
	cout << s.minDistance(word1, word2) << endl;
	
	return 0;
} 

代码2:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int minDistance(string word1, string word2)
    {
        int n = word1.size();
        int m = word2.size();

        if (n * m == 0)
        {
            return n + m;
        }

        int d[n + 1][m + 1];
        for (int i = 0; i < n + 1; ++i)
        {
            d[i][0] = i;
        }
        for (int i = 0; i < m + 1; ++i)
        {
            d[0][i] = i;
        }

        for (int i = 1; i < n + 1; ++i)
        {
            for (int j = 1; j < m + 1; ++j)
            {
                int left = d[i - 1][j] + 1;
                int down = d[i][j - 1] + 1;
                int left_down = d[i - 1][j - 1];
                if (word1[i - 1] != word2[j - 1])
                {
                    left_down += 1;
                }
                d[i][j] = min(left, min(down, left_down));
            }
        }
        return d[n][m];
    }
};

int main()
{
	Solution s;
	string word1 = "horse", word2 = "ros";
	cout << s.minDistance(word1, word2) << endl;
	
	word1 = "intention", word2 = "execution";
	cout << s.minDistance(word1, word2) << endl;
	
	return 0;
} 

代码3:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int minDistance(string word1, string word2)
    {
        int m = word1.size(), n = word2.size();

        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

        for (int i = 1; i <= n; ++i)
            dp[0][i] = dp[0][i - 1] + 1;
        for (int i = 1; i <= m; ++i)
            dp[i][0] = dp[i - 1][0] + 1;

        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                if (word1[i - 1] == word2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = min(min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i][j - 1]) + 1;
            }
        }
        return dp[m][n];
    }
};

int main()
{
	Solution s;
	string word1 = "horse", word2 = "ros";
	cout << s.minDistance(word1, word2) << endl;
	
	word1 = "intention", word2 = "execution";
	cout << s.minDistance(word1, word2) << endl;
	
	return 0;
} 

代码4:  

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.size();
        int len2 = word2.size();
        int **dp = new int *[len1 + 1];
        for (int i = 0; i < len1 + 1; i++)
            dp[i] = new int[len2 + 1];
        for (int i = 0; i < len1 + 1; i++)
            dp[i][0] = i;
        for (int i = 0; i < len2 + 1; i++)
            dp[0][i] = i;
        for (int i = 1; i < len1 + 1; i++) {
            for (int j = 1; j < len2 + 1; j++) {
                if (word1[i - 1] == word2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = (min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1);
            }
        }
        int res = dp[len1][len2];
        for (int i = 0; i < len1 + 1; i++)
            delete[] dp[i];
        delete[] dp;
        return res;
    }
};

int main()
{
	Solution s;
	string word1 = "horse", word2 = "ros";
	cout << s.minDistance(word1, word2) << endl;
	
	word1 = "intention", word2 = "execution";
	cout << s.minDistance(word1, word2) << endl;
	
	return 0;
} 

85. 最大矩形

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

示例 2:

输入:matrix = []
输出:0

示例 3:

输入:matrix = [["0"]]
输出:0

示例 4:

输入:matrix = [["1"]]
输出:1

示例 5:

输入:matrix = [["0","0"]]
输出:0

提示:

  • rows == matrix.length
  • cols == matrix[0].length
  • 0 <= row, cols <= 200
  • matrix[i][j] 为 '0' 或 '1'

代码1: 

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int maximalRectangle(vector<vector<char>> &matrix)
    {
        if (matrix.size() == 0)
        {
            return 0;
        }
        int maxarea = 0;
        int dp[matrix.size()][matrix[0].size()];
        memset(dp, 0, sizeof(dp));

        for (int i = 0; i < matrix.size(); ++i)
        {
            for (int j = 0; j < matrix[0].size(); ++j)
            {
                if (matrix[i][j] == '1')
                {
                    dp[i][j] = j == 0 ? 1 : dp[i][j - 1] + 1;
                    int width = dp[i][j];

                    for (int k = i; k >= 0; k--)
                    {
                        width = min(width, dp[k][j]);
                        maxarea = max(maxarea, width * (i - k + 1));
                    }
                }
            }
        }
        return maxarea;
    }
};

int main()
{
	Solution s;
	vector<vector<char>> matrix = {
		{'1','0','1','0','0'},
		{'1','0','1','1','1'},
		{'1','1','1','1','1'},
		{'1','0','0','1','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'1'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	return 0;
} 

代码2:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int maximalRectangle(vector<vector<char>> &matrix)
    {
        int res = 0;
        vector<int> height;
        for (int i = 0; i < matrix.size(); ++i)
        {
            height.resize(matrix[i].size());
            for (int j = 0; j < matrix[i].size(); ++j)
            {
                height[j] = matrix[i][j] == '0' ? 0 : (1 + height[j]);
            }
            res = max(res, largestRectangleArea(height));
        }
        return res;
    }

    int largestRectangleArea(vector<int> &heights)
    {
        if (heights.empty())
            return 0;
        stack<int> st;
        heights.push_back(0);
        int res0 = 0;
        for (int i = 0; i < heights.size(); i++)
        {
            while (!st.empty() && heights[i] < heights[st.top()])
            {
                int curHeight = heights[st.top()];
                st.pop();
                int width = st.empty() ? i : i - st.top() - 1;
                if (width * curHeight > res0)
                    res0 = width * curHeight;
            }
            st.push(i);
        }
        return res0;
    }
};

int main()
{
	Solution s;
	vector<vector<char>> matrix = {
		{'1','0','1','0','0'},
		{'1','0','1','1','1'},
		{'1','1','1','1','1'},
		{'1','0','0','1','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'1'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	return 0;
} 

代码3:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int largestRectangleArea(vector<int> &heights)
    {
        stack<int> h;
        heights.push_back(0);
        int ans = 0, hsize = heights.size();
        for (int i = 0; i < hsize; i++)
        {
            while (!h.empty() && heights[h.top()] > heights[i])
            {
                int top = h.top();
                h.pop();
                ans = max(ans, heights[top] * (h.empty() ? i : (i - h.top())));
            }
            h.push(i);
        }
        return ans;
    }

    int maximalRectangle(vector<vector<char>> &matrix)
    {
        if (matrix.empty())
            return 0;
        int n = matrix.size(), m = matrix[0].size(), ans = 0;
        vector<vector<int>> num(n, vector<int>(m, 0));
        for (int j = 0; j < m; j++)
        {
            num[0][j] = (matrix[0][j] == '0') ? 0 : 1;
            for (int i = 1; i < n; i++)
                num[i][j] = (matrix[i][j] == '0') ? 0 : num[i - 1][j] + 1;
        }
        for (int i = 0; i < n; i++)
        {
            int area = largestRectangleArea(num[i]);
            ans = max(ans, area);
        }
        return ans;
    }
};

int main()
{
	Solution s;
	vector<vector<char>> matrix = {
		{'1','0','1','0','0'},
		{'1','0','1','1','1'},
		{'1','1','1','1','1'},
		{'1','0','0','1','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'1'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	matrix = {{'0','0'}};
	cout << s.maximalRectangle(matrix) << endl;
	
	return 0;
} 

87. 扰乱字符串

使用下面描述的算法可以扰乱字符串 s 得到字符串 t :

  1. 如果字符串的长度为 1 ,算法停止
  2. 如果字符串的长度 > 1 ,执行下述步骤:
    • 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。
    • 随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。
    • 在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算法。

给你两个 长度相等 的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。如果是,返回 true ;否则,返回 false 。

示例 1:

输入:s1 = "great", s2 = "rgeat"

输出:true
解释:s1 上可能发生的一种情形是:
"great" --> "gr/eat" // 在一个随机下标处分割得到两个子字符串
"gr/eat" --> "gr/eat" // 随机决定:「保持这两个子字符串的顺序不变」
"gr/eat" --> "g/r / e/at" // 在子字符串上递归执行此算法。两个子字符串分别在随机下标处进行一轮分割
"g/r / e/at" --> "r/g / e/at" // 随机决定:第一组「交换两个子字符串」,第二组「保持这两个子字符串的顺序不变」
"r/g / e/at" --> "r/g / e/ a/t" // 继续递归执行此算法,将 "at" 分割得到 "a/t"
"r/g / e/ a/t" --> "r/g / e/ a/t" // 随机决定:「保持这两个子字符串的顺序不变」
算法终止,结果字符串和 s2 相同,都是 "rgeat"
这是一种能够扰乱 s1 得到 s2 的情形,可以认为 s2 是 s1 的扰乱字符串,返回 true

示例 2:

输入:s1 = "abcde", s2 = "caebd"
输出:false

示例 3:

输入:s1 = "a", s2 = "a"
输出:true

提示:

  • s1.length == s2.length
  • 1 <= s1.length <= 30
  • s1 和 s2 由小写英文字母组成

代码1:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    bool isScramble(string s1, string s2)
    {

        if (s1.size() != s2.size())
            return false;
        if (s1 == s2)
            return true;
        vector<int> hash(26, 0);

        for (int i = 0; i < s1.size(); i++)
            hash.at(s1[i] - 'a')++;

        for (int j = 0; j < s2.size(); j++)
            hash.at(s2[j] - 'a')--;

        for (int k = 0; k < 26; k++)
        {
            if (hash.at(k) != 0)
                return false;
        }

        for (int i = 1; i < s1.size(); i++)
        {
            if (
                (isScramble(s1.substr(0, i), s2.substr(0, i)) && isScramble(s1.substr(i, s1.size() - i), s2.substr(i, s1.size() - i))) || (isScramble(s1.substr(0, i), s2.substr(s1.size() - i)) && isScramble(s1.substr(i), s2.substr(0, s1.size() - i))))
                return true;
        }
        return false;
    }
};

int main()
{
	Solution s;
	cout << s.isScramble("great", "rgeat") << endl;
	cout << s.isScramble("abcde", "caebd") << endl;
	cout << s.isScramble("a", "a") << endl;
	
	return 0;
} 

代码2:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    bool isScramble(string s1, string s2)
    {
        int n1 = s1.length(), n2 = s2.length();
        if (n1 != n2)
            return false;
        vector<vector<vector<bool>>> dp(n1 + 1, vector<vector<bool>>(n1 + 1, vector<bool>(n1 + 1, false)));
        int i, j, k;
        for (i = 1; i <= n1; i++)
        {
            for (j = 1; j <= n1; j++)
            {
                dp[i][j][1] = (s1[i - 1] == s2[j - 1]);
            }
        }
        for (int len = 2; len <= n1; len++)
        {
            for (i = 1; i <= n1 && i + len <= n1 + 1; i++)
            {
                for (j = 1; j <= n1 && j + len <= n1 + 1; j++)
                {
                    for (k = 1; k < len; k++)
                    {
                        if (dp[i][j][k] && dp[i + k][j + k][len - k])
                        {
                            dp[i][j][len] = true;
                            break;
                        }
                        if (dp[i][j + len - k][k] && dp[i + k][j][len - k])
                        {
                            dp[i][j][len] = true;
                            break;
                        }
                    }
                }
            }
        }

        return dp[1][1][n1];
    }
};

int main()
{
	Solution s;
	cout << s.isScramble("great", "rgeat") << endl;
	cout << s.isScramble("abcde", "caebd") << endl;
	cout << s.isScramble("a", "a") << endl;
	
	return 0;
} 

代码3:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    bool isScramble(string s1, string s2)
    {
        if (s1.size() != s2.size())
            return false;
        if (s1 == s2)
            return true;
        string str1 = s1, str2 = s2;
        sort(str1.begin(), str1.end());
        sort(str2.begin(), str2.end());
        if (str1 != str2)
            return false;
        for (int i = 1; i < s1.size(); ++i)
        {
            string s11 = s1.substr(0, i);
            string s12 = s1.substr(i);
            string s21 = s2.substr(0, i);
            string s22 = s2.substr(i);
            if (isScramble(s11, s21) && isScramble(s12, s22))
                return true;
            s21 = s2.substr(s2.size() - i);
            s22 = s2.substr(0, s2.size() - i);
            if (isScramble(s11, s21) && isScramble(s12, s22))
                return true;
        }
        return false;
    }
};

int main()
{
	Solution s;
	cout << s.isScramble("great", "rgeat") << endl;
	cout << s.isScramble("abcde", "caebd") << endl;
	cout << s.isScramble("a", "a") << endl;
	
	return 0;
} 

91. 解码方法

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> 1'B' -> 2...'Z' -> 26

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

  • "AAJF" ,将消息分组为 (1 1 10 6)
  • "KJF" ,将消息分组为 (11 10 6)

注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

示例 1:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2:

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

示例 3:

输入:s = "0"
输出:0
解释:没有字符映射到以 0 开头的数字。含有 0 的有效映射是 'J' -> "10" 和 'T'-> "20" 。由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。

示例 4:

输入:s = "06"
输出:0
解释:"06" 不能映射到 "F" ,因为字符串含有前导 0("6" 和 "06" 在映射中并不等价)。

提示:

  • 1 <= s.length <= 100
  • s 只包含数字,并且可能包含前导零。

代码1: 

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int numDecodings(string s)
    {
        vector<int> nums(s.size());
        if (s[0] == '0')
        {
            return 0;
        }
        nums[0] = 1;

        if (s.size() > 1)
        {
            if (s[1] != '0')
            {
                nums[1] += 1;
            }
            if ((s[0] - '0') * 10 + (s[1] - '0') <= 26)
            {
                nums[1] += 1;
            }
        }

        for (int i = 2; i < s.size(); i++)
        {
            if (s[i] != '0')
            {
                nums[i] += nums[i - 1];
            }
            if (s[i - 1] != '0' && ((s[i - 1] - '0') * 10 + (s[i] - '0') <= 26))
            {
                nums[i] += nums[i - 2];
            }
        }
        return nums[s.size() - 1];
    }
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

代码2:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int numDecodings(string s)
    {
        int n = s.size();
        if (s.empty())
            return 0;
        if (s[0] == '0')
            return 0;
        vector<int> info(n + 1, 0);
        info[0] = 1;
        info[1] = 1;
        for (int i = 2; i < n + 1; ++i)
        {
            if (s[i - 1] != '0')
                info[i] += info[i - 1];
            if (s.substr(i - 2, 2) <= "26" && s.substr(i - 2, 2) >= "10")
                info[i] += info[i - 2];
        }
        return info[n];
    }
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

代码3:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int dp(string &s, int i, int j)
    {
        int n = j - i + 1;
        if (n == 0)
            return 0;
        if (n == 1)
            return s[i] == '0' ? 0 : 1;
        if (n == 2)
        {
            if (s[i] == '0')
                return 0;
            if (s[i] > '2')
                return s[j] == '0' ? 0 : 1;
            if (s[i] == '2' && s[j] > '6')
                return 1;
            if (s[j] == '0')
                return 1;
            return 2;
        }
        if (s[i] > '2')
            return dp(s, i + 1, j);
        if (s[i] == '2')
        {
            if (s[i + 1] == '0')
                return dp(s, i + 2, j);
            else if (s[i + 1] < '7')
                return dp(s, i + 1, j) + dp(s, i + 2, j);
            else
                return dp(s, i + 1, j);
        }
        if (s[i] == '0')
            return 0;
        if (s[i + 1] == '0')
            return dp(s, i + 2, j);
        return dp(s, i + 1, j) + dp(s, i + 2, j);
    }
    int numDecodings(string s)
    {
        return dp(s, 0, s.size() - 1);
    }
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

代码4:  

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> f(n + 1);
        f[0] = 1;
        for (int i = 1; i <= n; ++i) {
            if (s[i - 1] != '0') {
                f[i] += f[i - 1];
            }
            if (i > 1 && s[i - 2] != '0' && ((s[i - 2] - '0') * 10 + (s[i - 1] - '0') <= 26)) {
                f[i] += f[i - 2];
            }
        }
        return f[n];
    }
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

代码5:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int numDecodings(string s)
    {
        if (s.empty() || s[0] == '0')
            return 0;
        vector<int> dp(s.size() + 1, 0);
        dp[0] = 1;
        for (int i = 1; i < dp.size(); ++i)
        {
            dp[i] = (s[i - 1] == '0') ? 0 : dp[i - 1];
            if (i > 1 && (s[i - 2] == '1' || (s[i - 2] >= '2' && s[i - 1] <= '6')))
                dp[i] += dp[i - 2];
        }
        return dp[s.size()];
    }
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

代码6:  

#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
	int numDecodings(string s) {
	    if (s.empty() || s[0] == '0') {
	        return 0;
	    }
	    vector<int> dp(s.size() + 1, 1);
	    for (int i = 2; i < dp.size(); ++i){
	        dp[i] = ((s[i-1] == '0') ? 0 : dp[i-1]);
	        if (s[i-2] == '1' || (s[i-2] == '2' && s[i-1] <= '6')){
	            dp[i] += dp[i-2];
	        }
	    }
	    return dp.back();
	}
};

int main()
{
	Solution s;
	cout << s.numDecodings("12") << endl;
	cout << s.numDecodings("226") << endl;
	cout << s.numDecodings("0") << endl;
	cout << s.numDecodings("06") << endl;
	
	return 0;
} 

前:​https://hannyang.blog.csdn.net/article/details/129287197​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/832791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫007_python中的输出以及格式化输出_以及输入---python工作笔记025

首先看输出 输出这里,注意不能直接上面这样,18需要转换成字符串 可以看到python中这个字符串和数字一起的时候,数字要转换一下成字符串. 然后这里要注意%s 和%d,这个s指的是字符串,d指的是数字 注意后面的内容前面要放个% ,然后多个参数的话,那么这里用(),里面用,号隔开 然…

寄存器详解(一)

目录 前言&#xff1a; 通用寄存器 示例&#xff1a; 通用寄存器的划分 汇编指令 cpu物理地址的形成 地址加法器运算示例&#xff1a; 1. 相关部件提供段地址和偏移地址 2. 段地址和偏移地址送入地址加法器 3. 段地址*16 4. 求出物理地址 5. 输出物理地址 段的概念 Deb…

SRM系统:提升供应商关系管理的利器

在现代供应链管理中&#xff0c;供应商关系的稳定和优化对企业的成功至关重要。为了更好地管理和维护供应商关系&#xff0c;许多企业开始利用供应商关系管理&#xff08;SRM&#xff09;系统。本文将围绕SRM系统的功能&#xff0c;探讨其在供应链管理中的重要性和优势。 一、…

大模型时代下,算法工程师该何去何从?

目录 一、大模型时代的罪与罚1.1、快速演进的大模型技术1.2、模型表现出的惊人创造力1.3、大模型AI对算法工程师的威胁性 二、算法工程师的破与发2.1、破——大模型时代给算法工程师带来的新机遇2.2、发——算法工程师如何适应大模型时代的变革 三、大模型时代下人才发展洞察 大…

卷积神经网络【图解CNN】

文章目录 1.卷积运算2.池化3.全连接层 卷积神经网络可以看作一个函数或者黑箱&#xff0c;输入就是图片的像素阵列&#xff0c;输出就是这个图片是什么&#xff1f; 图片是X&#xff0c;那么就输出‘x’&#xff0c;图片是‘O’,那么就输出O&#xff1b; 在计算机眼中&#xff…

Spring Boot 系列4 -- 统一功能处理

目录 前言 1. Spring AOP 用户统⼀登录验证的问题 1.1 自定义拦截器 1.2 配置拦截器并配置拦截的规则 1.3 拦截器的原理源码分析 2. 统一异常处理 2.1 实现统一异常处理 2.2 测试统一异常处理 3. 统一的数据格式返回 3.1 统⼀数据返回格式的实现 3.2 测试统一的数据返…

struct iovec结构体使用

参考 struct iovec 结构体定义与使用 iovec介绍 是一个I/O向量。是与readv和writev操作相关的结构体&#xff0c;readv和writev函数用于在一次函数调用中读、写多个非连续缓冲区。有时也将这两个函数称为散布读&#xff08;scatter read&#xff09;和聚集写&#xff08;gath…

爬虫008_流程控制语句_if_if else_elif_for---python工作笔记026

然后我们再来看一下这里的,判断,可以看到 再看一个判断,这里的布尔类型 第二行有4个空格,python的格式 注意这里,输入的age是字符串,需要转一下才行 int可以写到int(intput("阿斯顿法师打发地方")) 这样也可以

【算法心得】C++map用不着map.find(arr[j])!=map.end();js的map是map不是哈希;编译器选GNU

https://leetcode.com/problems/count-of-range-sum/ https://vjudge.csgrandeur.cn/problem/CodeForces-459D 这两题都是线段树&#xff0c;很明显的单点修改区间查询 leetcode那题我觉得map用hashmap就行&#xff0c;但是好像js里没有hashmap&#xff0c;那就 Map() 也行吧…

webpack复习

webpack webpack复习 webpack基本配置 拆分配置 - 公共配置 生产环境配置 开发环境配置 使用merge webpack-dev-server 启动本地服务 在公共中引入babel-loader处理es6 webpack高级配置 多入口文件 enty 入口为一个对象 里面的key为入口名 value为入口文件路径 例如 pa…

【EI/SCOPUS征稿】第三届智能电网与能源互联网国际会议(SGEI 2023)

第三届智能电网与能源互联网国际会议&#xff08;SGEI 2023&#xff09; 2023 3rd International Conference on Smart Grid and Energy Internet 为交流近年来国内外在智能电网和能源互联网领域的理论、技术和应用的最新进展&#xff0c;展示最新成果&#xff0c;2023年第三…

TSINGSEE青犀视频安防监控EasyCVR视频汇聚平台电子地图定位偏移的排查与解决

安防监控EasyCVR视频汇聚综合管理平台具有强大的数据接入、处理及分发能力&#xff0c;平台可提供视频监控直播、云端录像、云存储、录像检索与回看、告警上报与查询、平台级联、云台控制、语音对讲、电子地图、轨迹跟踪、H.265自动转码等视频能力。 在视频监控管理平台TSINGSE…

第二章:多态

系列文章目录 文章目录 系列文章目录前言多态的概念概念 多态的定义及实现多态的构成条件虚函数虚函数的重写C11 override 和 final重载、覆盖(重写)、隐藏(重定义)的对比 抽象类概念接口继承和实现继承 多态的原理虚函数表多态的原理动态绑定与静态绑定 单继承和多继承关系的虚…

外网渗透信息收集漏洞挖掘

外网渗透信息收集&漏洞挖掘 信息收集一、“资产收集”的重要性二、企业信息收集之域名信息收集2.1、通过域名找到公司2.2、通过公司找到域名3.3、收集每个域名的⼦域名 三、企业信息信息收集之移动资产3.1、移动端APP收集3.2、微信⼩程序收集 四、信息收集流程漏洞挖掘一、…

《面试1v1》ElasticSearch 和 Lucene

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

自动化应用杂志自动化应用杂志社自动化应用编辑部2023年第11期目录

数据处理与人工智能 大数据视域下无轨设备全生命周期健康管理技术的研究 赖凡; 1-3 三维激光扫描结合无人机倾斜摄影在街区改造测绘中的技术应用 张睿; 4-6 井上变电站巡检机器人的设计与应用 刘芳; 7-9 《自动化应用》投稿邮箱&#xff1a;cnqikantg126.com 基于机…

出现一次的数字(其他数字出现三次,两次)

位运算的知识点&#xff1a; 异或运算具有以下几个重要性质 交换律&#xff1a;a ^ b b ^ a 结合律&#xff1a;a ^ (b ^ c) (a ^ b) ^ c 任何数与0异或等于它本身&#xff1a;a ^ 0 a 任何数与自身异或等于0&#xff1a;a ^ a 0 对于数组中所有元素进行异或运算&#xf…

【前端实习生备战秋招】—HTML 和 CSS面试题总结(一)

【前端实习生备战秋招】—HTML 和 CSS面试题总结&#xff08;一&#xff09; 1. 你做的页面在哪些流览器测试过&#xff1f;这些浏览器的内核分别是什么? IE:trident内核 Firefox&#xff1a;gecko内核 Safari:webkit内核 Opera:以前是presto内核&#xff0c;Opera现已改用Goo…

接口测试如何在json中引用mock变量

在测试接口的时候&#xff0c;有的接口需要测试随机传入大量数据&#xff0c;查看数据库是否正常&#xff0c;但是大量的随机数据全靠自己手写会很慢&#xff0c;而且是通过json传递的数据。 这里我们就可以使用mock生成随机变量&#xff0c;然后在json中引用mock变量 首先看…

LeetCode面向运气之Javascript—第2500题-删除每行中的最大值-93.51%

LeetCode第2500题-删除每行中的最大值 题目要求 一个 m x n 大小的矩阵 grid &#xff0c;由若干正整数组成。 执行下述操作&#xff0c;直到 grid 变为空矩阵&#xff1a; 从每一行删除值最大的元素。如果存在多个这样的值&#xff0c;删除其中任何一个。 将删除元素中的最…