Bootstrap

力扣 205. 同构字符串,1309. 解码字母到整数映射,91. 解码方法,200. 岛屿数量,639. 解码方法 II

205. 同构字符串

题目

给定两个字符串 s 和 t ,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

提示:

  1. 1 <= s.length <= 5 * 10^4
  2. t.length == s.length
  3. s 和 t 由任意有效的 ASCII 字符组成

AC代码

// 通过判断什么时候出现不同字符
class Solution {
public:
    bool isIsomorphic(string s, string t) {
        map<char,int>S;
        map<char,int>T;
        int ss=0,tt=0;
        for(int i=0;i<s.size();i++)
        {
            if(!S[s[i]])    S[s[i]]=++ss; // S串 中新的字符出现,标记
            if(!T[t[i]])   T[t[i]]=++tt; // T串 中新的字符出现,标记
            if(S[s[i]]!=T[t[i]])    return false;   // 字符标记不同,则字符规律不同
        }
        return true;
    }
};

1309. 解码字母到整数映射

题目

给你一个字符串 s,它由数字(‘0’ - ‘9’)和 ‘#’ 组成。我们希望按下述规则将 s 映射为一些小写英文字符:

情况1:字符(‘a’ - ‘i’)分别用(‘1’ - ‘9’)表示。
情况2:字符(‘j’ - ‘z’)分别用(‘10#’ - ‘26#’)表示。
返回映射之后形成的新字符串。

题目数据保证映射始终唯一。

提示:

  1. 1 <= s.length <= 1000
  2. s[i] 只包含数字(‘0’-‘9’)和 ‘#’ 字符。
  3. s 是映射始终存在的有效字符串。

AC代码

class Solution {
public:
    string freqAlphabets(string s) {
        string ans;
        int i;
        for(i=0;i<s.size();i++)
        {
        	int f=0;
            if(i+2<s.size()&&isdigit(s[i])&&isdigit(s[i+1])&&s[i+2]=='#') // 出现 情况 2
            {
            	int x=(s[i]-'0')*10+(s[i+1]-'0');
                ans+=x+'a'-1;
                f=1; // 跳过已使用字符
			}
            else // 出现	情况 1
            {
                int x=(s[i]-'0');
                ans+=x+'a'-1;
            }
            if(f==1)	i=i+2; // 对下标操作,跳过已使用字符
        }
        return ans;
    }
};

91. 解码方法

题目

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

“1” -> ‘A’

“2” -> ‘B’

“25” -> ‘Y’

“26” -> ‘Z’

然而,在 解码 已编码的消息时,你意识到有许多不同的方式来解码,因为有些编码被包含在其它编码当中(“2” 和 “5” 与 “25”)。

例如,“11106” 可以映射为:

“AAJF” ,将消息分组为 (1, 1, 10, 6)
“KJF” ,将消息分组为 (11, 10, 6)
消息不能分组为 (1, 11, 06) ,因为 “06” 不是一个合法编码(只有 “6” 是合法的)。
注意,可能存在无法解码的字符串。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。如果没有合法的方式解码整个字符串,返回 0。

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

提示:

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

AC代码

class Solution {
public:
    int numDecodings(string s) {
        if(s.size()==0||s[0]=='0')return 0;
        vector<int>dp(s.size()+1,0);
        dp[0] = 1;
        for(int i=1;i<=s.size();i++)
        {
            dp[i] = s[i-1]=='0' ? 0 : dp[i-1]; // 当前一位为 '0'时,则无法与当前形成一个字符,无法继承前一位的种类,否则继承前一位的种类
            if(i > 1 && (s[i-2] == '1' || (s[i-2] == '2' &&s[i-1]<= '6'))) // 当前一位与前二位可以形成,则继承前二位的种类
            {
                dp[i] += dp[i-2];
            }
        }
        return dp[s.size()];
    }
};

200. 岛屿数量

题目

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

提示:

  1. m == grid.length
  2. n == grid[i].length
  3. 1 <= m, n <= 300
  4. grid[i][j] 的值为 ‘0’ 或 ‘1’

AC代码

// dfs 向各个可行方向行走
class Solution {
public:
    int n,m;
    int numIslands(vector<vector<char>>& grid) {
        int ans=0;
        n=grid.size(),m=grid[0].size();
        queue< pair<int,int> >q;
        map<pair<int,int> ,int >mp;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(grid[i][j]=='1')
                {
                    ans++;
                    dfs(grid,i,j);
                }
            }
        }
        return ans;
    }
    void dfs(vector<vector<char> >& grid,int x,int y)
    {
        grid[x][y]='0';
        if(x-1>=0&&grid[x-1][y]=='1')   dfs(grid,x-1,y);
        if(y-1>=0&&grid[x][y-1]=='1')   dfs(grid,x,y-1);
        if(x+1<n&&grid[x+1][y]=='1')    dfs(grid,x+1,y);
        if(y+1<m&&grid[x][y+1]=='1')    dfs(grid,x,y+1);
    }
};

639. 解码方法 II

题目

一条包含字母 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” 不同。

除了 上面描述的数字字母映射方案,编码消息中可能包含 '’ 字符,可以表示从 ‘1’ 到 ‘9’ 的任一数字(不包括 ‘0’)。例如,编码字符串 "1" 可以表示 “11”、“12”、“13”、“14”、“15”、“16”、“17”、“18” 或 “19” 中的任意一条消息。对 “1*” 进行解码,相当于解码该字符串可以表示的任何编码消息。

给你一个字符串 s ,由数字和 ‘*’ 字符组成,返回 解码 该字符串的方法 数目 。

由于答案数目可能非常大,返回 10^9 + 7 的 模 。

提示:

  1. 1 <= s.length <= 105
  2. s[i] 是 0 - 9 中的一位数字或字符 ‘*’

AC代码

class Solution {
public:
    int numDecodings(string s) {
        int n=s.size();
        if(n==0||s[0]=='0')  return 0;
        if(n==1)
        {
            if(s[0]=='*')   return 9;
            else    return 1;
        }
        vector<long long > dp(n+1);
        dp[0]=1;
        dp[1]= s[0]=='*' ? 9 : 1; // 第一个字符处理
        char a,b;
        for(int i=2;i<=n;i++) // 从第二个字符开始,列举出所有当前位与前一位的情况
        {
            a=s[i-2],b=s[i-1];
            if(b=='*')  dp[i]+=9*dp[i-1]; // 当前为字符为 '*',继承前一位种类的 9 倍
            else if(b>'0')  dp[i]+=dp[i-1]; // 当前字符不为 '0'和'#',继承前一位种类

            if(a=='*') // 前一位为 '*'
            {
                if(b=='*') // 当前字符为 '*'
                {
                    dp[i]+=15*dp[i-2];
                }
                else if(b<='6') // 当前字符不为 '*',且小于 6 
                {
                    dp[i]+=2*dp[i-2];
                }
                else    dp[i]+=dp[i-2]; // // 当前字符不为 '*',且大于 6 
            }
            else if(a=='1'||a=='2') // 前一位为 '1' 或 '2'
            {
                if(b=='*') // 当前字符为'*'
                {
                    dp[i]+= a=='1' ? 9*dp[i-2] : 6*dp[i-2];
                }
                else if((a-'0')*10 + b-'0' <=26) // 当前字符不为'*',判断是否成立
                {
                    dp[i]+=dp[i-2];
                }
            }
            dp[i]%=1000000007; // 取模
        }
        return (int)dp[n];
    }
};
;