[Leetcode] 97, 168, 87

97. Interleaving String

Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

Solution: 动规,直接深搜会超时。设f(x1,x2)表示s1的前x1位和s2的前x2位能够匹配到s3(即s3的前x1+x2位),则状态转移方程为:

f(x1, x2) = {f(x1-1,x2) && (s3(x1+x2-1) == s1(x1-1))}
            || {f(x1,x2-1) && (s3(x1+x2-1) == s2(x2-1))};

从此方程可以看出,每一次计算的时候实际只会调用到前一行或前一列的数据而不会调用更早的数据,因此可以使用滚动数组来将内存压缩到O(n)。

Code:

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if(s3.size()!=s1.size()+s2.size()) return false; //注意特殊情况
        vector<bool> f(s1.size()+1, false);
        f[0] = true;
        for(int t=1; t<=s1.size(); t++){
            f[t] = f[t-1] && (s3[t-1]==s1[t-1]);
        }
        for(int i=1; i<=s2.size(); i++){
            f[0] = f[0]&&(s3[i-1]==s2[i-1]);
            for(int t=1; t<=s1.size(); t++){
                f[t] = (f[t]&&(s3[i+t-1]==s2[i-1])) //s3当前字符匹配到s2的情况
                    ||(f[t-1]&&(s3[i+t-1]==s1[t-1])); //s3当前字符匹配到s1的情况
            }
        }
        return f[s1.size()];
    }
};


168. Excel Sheet Column Title

Given a positive integer, return its corresponding column title as appear in an Excel sheet.

For example:

    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 

Credits:
Special thanks to @ifanchu for adding this problem and creating all test cases.

Solution: 进制转换的问题,但是注意+1的位置容易搞错,因为是从1开始的。倒过来的转换想起来比较简单,从字符串转换成数字:

class Solution {
public:
    int titleToNumber(string s) {
        int ans = 0;
        for(int i=0; s[i]; i++){
            ans = ans*26 + s[i]-'A'+1;
        }
        return ans;
    }
};

因此将转换公式倒过来就是s[i] = cur%26 - 1 + 'A'。

Code:

class Solution {
public:
    string convertToTitle(int n) {
        string ans = "";
        while(n>0){
            n = n-1;
            ans.insert(ans.begin(), n%26+'A');
            n = n/26;
        }
        return ans;
    }
};


87. Scramble String

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a

We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Solution: 动规。注意:本题每次分割是任意取一个分割点,不一定要选择中点,因此状态转移方程为:

f[n][i][j] = (f[k][i][j] && f[n-k][i+k][j+k]) || (f[k][i][j+n-k] && f[n-k][i+k][j])(k为分割点)

Code:

class Solution {
public:
    bool isScramble(string s1, string s2) {
        if(s1.size()!=s2.size()) return false;
        if(s1.size()==1) return s1[0]==s2[0];
        
        const int N = s1.size();
        bool f[N][N][N+1];
        fill_n(&f[0][0][0], N*N*(N+1), false);
        for(int x1=0; x1<N; x1++){
            for(int x2=0; x2<N; x2++){
                f[x1][x2][1] = (s1[x1]==s2[x2]);
            }
        }
        for(int n=2; n<=N; n++){
            for(int x1=0; x1+n<=N; x1++){
                for(int x2=0; x2+n<=N; x2++){
                    for(int k=1; k<n; k++){
                        if((f[x1][x2][k] && f[x1+k][x2+k][n-k])
                            || (f[x1][x2+(n-k)][k] && f[x1+k][x2][n-k])){
                            f[x1][x2][n] = true;
                            break;
                        }
                    }
                }
            }
            
        }
        return f[0][0][N];
        
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值