LeetCode : 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 ifs2 is a scrambled string ofs1.

看完题彻底懵了啊有木有。以为有什么高端的解法,结果上论坛上看了看,差不多也是暴力搜索。就自己写了一下。这里map不是必须的,只是不用的话会超时。

class Solution {
public:
    bool isScramble(string s1, string s2) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        static map<string, bool> map;
        if(s1 == s2)return true;
        int n1 = s1.size();
        int n2 = s2.size();
        
        if(n2 != n1) {
            return false;
        }
        if(n1 == 1 && n2 == 1 && s1 != s2) return false;
        string key = s1 + s2;
        if(map.find(key) != map.end()) return map[key];
        
        for(int i = 1; i < n1; ++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)){
                map[key] = true;
                return true;
            }
            s21 = s2.substr(n1 - i);
            s22 = s2.substr(0, n1 - i);
            if(isScramble(s11,s21) && isScramble(s12, s22)){
                map[key] = true;
                return true;
            }
        }
        map[key] = false;
        return false;
    }
};


又看了看,更好的算法果然是有的,用动态规划。

维护一个三维的数组:res[ len ][ start_s1 ][ start_s2 ]表示长度为len的,s1从start_s1开始,s2从start_s2开始是否能scramble。

然后递归方程为:res[len][start_s1][start_s2] = (res[m][start_s1][start_s2] && res[len - m][start_s1 + m][start_s2 + m])

||(res[m][start_s1][start_s2 + len - m] && res[len-m][start_s1 + m][start_s2])。

其中m是1到len-1的一个数。

base case 是:如果len等于1的话, res[len][start_s1][start_s2] = (s1[start_s1] == s2[start_s2]);


class Solution {
public:
     bool isScramble(string s1, string s2) {
        if(s1.size() != s2.size()) return false;
        if(s1.size() == 0) return true;
        if(s1 == s2) return true;
        int n = s1.size();
        bool *** res = new bool **[n+1];
        for(int i = 1; i<= n; ++i){
            res[i] = new bool*[n];
            int len = i;
            int start_s1 = 0;
            int start_s2 = 0;
            for(int j = 0; j <= n-len; ++j){//对s1的下标进行循环
                start_s1 = j;
                res[len][start_s1] = new bool[n];
                for(int k = 0; k<= n-len; ++k){//对s2的下标进行循环
                    start_s2 = k;
                    res[len][start_s1][start_s2] = false;
                    if(len == 1){
                        res[len][start_s1][start_s2] = s1[start_s1] == s2[start_s2];
                    }
                    for(int m = 1; m < len; ++m){//判断子序列
                        if(res[m][start_s1][start_s2] && res[len - m][start_s1 + m][start_s2 + m]){
                            res[len][start_s1][start_s2] = true;
                            break;
                        }
                        if(res[m][start_s1][start_s2 + len - m] &&
                        res[len-m][start_s1 + m][start_s2]){
                            res[len][start_s1][start_s2] = true;
                            break;
                        }
                    }
                }
            }
        }
        return res[n][0][0];
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值