算法进修Day-22

算法进修Day-22

43. 字符串相乘

难度:中等
题目要求:
给定两个以字符串形式表示的非负整数num1num2,返回num1num2的乘积,它们的乘积也表示为字符串形式

示例1

输入:num1 = “2”, num2 = “3”
输出:“6”

示例2

输入:num1 = “123”, num2 = “456”
输出:“56088”

题解

创建一个字符串构造器 s u m sum sum,内部初始值为'0',长度为 n u m 1 num1 num1 n u m 2 num2 num2的和,对两个字符串从右到左遍历。

s u m sum sum的第 i + j + 1 i+j+1 i+j+1 的位置赋值:

  • 定义一个 n e x t = s u m [ i + j + 1 ] − ′ 0 ′ + ( n u m 1 [ i ] − ′ 0 ′ ) ∗ ( n u m 2 [ j ] − ′ 0 ′ ) next=sum[i+j+1]-'0'+(num1[i]-'0')*(num2[j]-'0') next=sum[i+j+1]0+(num1[i]0)(num2[j]0),以为两个字符串内的单个元素为 c h a r char char,所以需要减去一个'0'来讲他转换为 i n t int int类型
  • n e x t % 10 + ′ 0 ′ next\%10+'0' next%10+0 的值转换为 c h a r char char 类型之后将结果存入到 s u m [ i + j + 1 ] sum[i+j+1] sum[i+j+1]

s u m sum sum的第 i + j i+j i+j的位置进行赋值

  • n e x t / 10 next/10 next/10的值转换为 c h a r char char 类型之后将结果存入到 s u m [ i + j ] sum[i+j] sum[i+j]

最后定义一个字符串res,将sum从头删除为'0'的元素之后转换为字符串
如果res的长度为0,那么直接返回"0",否则直接返回res

想法代码

using System.Text;

class Solution
{
    public static void Main(String[] args)
    {
        string num1 = "123456789";
        string num2 = "987654321";
        Solution solution = new Solution();
        string res = solution.Multiply(num1, num2);
        Console.WriteLine(res);
    }

    public string Multiply(string num1, string num2)
    {
        StringBuilder sum = new StringBuilder(new string('0', num1.Length + num2.Length));
        for (int i = num1.Length - 1; i >= 0; i--)
        {
            for (int j = num2.Length - 1; j >= 0; j--)
            {
                int next = sum[i + j + 1] - '0' + (num1[i] - '0') * (num2[j] - '0');
                sum[i + j + 1] = (char)(next % 10 + '0');
                sum[i + j] += (char)(next / 10);
            }
        }
        string res = sum.ToString().TrimStart('0');
        return res.Length == 0 ? "0" : res;
    }
}

44. 通配符匹配

难度:困难
题目要求:
给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?''*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • ‘*'可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够完全匹配输入字符串(而不是部分匹配)。

示例1

输入:s = “aa”, p = “a”
输出:false

示例2

输入:s = “aa”, p = “*”
输出:true

示例3

输入:s = “cb”, p = “?a”
输出:false

题解

判断 s s s p p p 是否匹配,需要分别考虑 s s s p p p 的每个前缀,用 m m m n n n 分别表示 s s s p p p 的长度。对于满足 1 ≤ j ≤ n 1\leq j\leq n 1jn 1 ≤ i ≤ m 1\leq i\leq m 1im 的每个下标对 ( i , j ) (i,j) (i,j),需要分别计算 s s s 的前 i i i个字符和 p p p 的前 j j j 个字符是否匹配

创建 ( m + 1 ) ∗ ( n + 1 ) (m+1)*(n+1) (m+1)(n+1) 的二维数组 d p dp dp,其中 d p [ i ] [ j ] dp[i][j] dp[i][j] s s s 的前 i i i 个字符和 p p p 的前 j j j 个字符是否匹配

j = 0 j=0 j=0 时,模式为空,只有空字符串可以匹配,因此动态规划的结果:当 i = 0 i=0 i=0 时, d p [ i ] [ j ] = t r u e dp[i][j]=true dp[i][j]=true;当 i > 0 i>0 i>0 时, d p [ i ] [ 0 ] = f a l s e dp[i][0]=false dp[i][0]=false

j > 0 j>0 j>0 时,动态规划的状态转移方程如下:

  • i = 0 i=0 i=0 j > 0 j>0 j>0 时,如果 p [ j − 1 ] = ′ ∗ ′ p[j-1]='*' p[j1]= d p [ i ] [ j − 1 ] = t r u e dp[i][j-1]=true dp[i][j1]=true d p [ i ] [ j ] = t r u e dp[i][j]=true dp[i][j]=true,否则 d p [ i ] [ j ] = f a l s e dp[i][j]=false dp[i][j]=false
  • i > 0 i>0 i>0 j > 0 j>0 j>0 时,考虑以下情况
    • 如果 p [ j − 1 ] ≠ ′ ∗ ′ p[j-1]\neq '*' p[j1]= ,则当 d p [ i − 1 ] [ j − 1 ] = t r u e dp[i-1][j-1]=true dp[i1][j1]=true s [ i − 1 ] , p [ j − 1 ] s[i-1],p[j-1] s[i1]p[j1] 满足字符匹配时 d p [ i ] [ j ] = t r u e dp[i][j]=true dp[i][j]=true,否则 d p [ i ] [ j ] = f a l s e dp[i][j]=false dp[i][j]=false
    • 如果 p [ j − 1 ] = ′ ∗ ′ p[j-1]='*' p[j1]= ,则当 d p [ i ] [ j − 1 ] = t r u e dp[i][j-1]=true dp[i][j1]=true d p [ i − 1 ] [ j ] = t r u e dp[i-1][j]=true dp[i1][j]=true d p [ i ] [ j ] = t r u e dp[i][j]=true dp[i][j]=true,否则 d p [ i ] [ j ] = f a l s e dp[i][j]=false dp[i][j]=false

根据动态规划的状态转移方程,计算 d p [ i ] [ j ] dp[i][j] dp[i][j] 的顺序为从小到大遍历每一个 i i i,对于每个 i i i 从小到大遍历每一个 j j j。计算得到 d p [ i ] [ j ] dp[i][j] dp[i][j]

想法代码

public class Solution
{
    public static void Main(string[] args)
    {
        string s = "aa";
        string p = "a";
        Solution solution = new Solution();
        bool res = solution.IsMatch(s,p);
        Console.WriteLine(res);
    }

    public bool IsMatch(string s, string p)
    {
        int m = s.Length, n = p.Length;
        bool[] dp = new bool[n + 1];
        dp[0] = true;
        for (int j = 1; j <= n; j++)
        {
            if (p[j - 1] == '*')
            {
                dp[j] = dp[j - 1];
            }
        }
        for (int i = 1; i <= m; i++)
        {
            bool[] dpNew = new bool[n + 1];
            char c1 = s[i - 1];
            for (int j = 1; j <= n; j++)
            {
                char c2 = p[j - 1];
                if (c2 != '*')
                {
                    dpNew[j] = dp[j - 1] && IsCharacterMatch(c1, c2);
                }
                else
                {
                    dpNew[j] = dpNew[j - 1] || dp[j];
                }
            }
            dp = dpNew;
        }
        return dp[n];
    }

    public bool IsCharacterMatch(char c1, char c2)
    {
        return c1 == c2 || c2 == '?';
    }
}

你可能感兴趣的:(算法进修,算法,leetcode,c#)