LeetCode 13.7 Scramble String

19 篇文章 0 订阅
11 篇文章 0 订阅

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.

递归

// LeetCode, Interleaving String

// 递归,会超时,仅用来帮助理解

// 时间复杂度 O(n^6),空间复杂度 O(1)

class Solution {

public:

    bool isScramble(string s1, string s2) {

        return isScramble(s1.begin(), s1.end(), s2.begin());

    } private:

    typedef string::iterator Iterator;

    bool isScramble(Iterator first1, Iterator last1, Iterator first2) {

        auto length = distance(first1, last1);

        auto last2 = next(first2, length);

        if (length == 1) return *first1 == *first2;

        for (int i = 1; i < length; ++i)

            if ((isScramble(first1, first1 + i, first2)

                 && isScramble(first1 + i, last1, first2 + i))

                || (isScramble(first1, first1 + i, last2 - i) && isScramble(first1 + i, last1, first2)))

                return true;

        return false;

    }

};

动规

// LeetCode, Interleaving String

// 动规,时间复杂度 O(n^3),空间复杂度 O(n^3)

class Solution {

public:

    bool isScramble(string s1, string s2) {

        const int N = s1.size();

        if (N != s2.size()) return false;

        // f[n][i][j],表示长度为 n,起点为 s1[i] // 起点为 s2[j] 两个字符串是否互为 scramble 

bool f[N + 1][N][N];

        fill_n(&f[0][0][0], (N + 1) * N * N, false);

        for (int i = 0; i < N; i++)

            for (int j = 0; j < N; j++)

                f[1][i][j] = s1[i] == s2[j];

        for (int n = 1; n <= N; ++n) {

            for (int i = 0; i + n <= N; ++i) {

                for (int j = 0; j + n <= N; ++j) {

                    for (int k = 1; k < n; ++k) {

                        if ((f[k][i][j] && f[n - k][i + k][j + k]) ||(f[k][i][j + n - k] && f[n - k][i + k][j])) {

                            f[n][i][j] = true;

                            break;

                        } }

                } }

        }

        return f[N][0][0];

    }

};

递归 + 剪枝

// LeetCode, Interleaving String

// 递归 + 剪枝

// 时间复杂度 O(n^6),空间复杂度 O(1)

class Solution {

public:

    bool isScramble(string s1, string s2) {

        return isScramble(s1.begin(), s1.end(), s2.begin());

    } private:

    typedef string::iterator Iterator;

    bool isScramble(Iterator first1, Iterator last1, Iterator first2) {

        auto length = distance(first1, last1);

        auto last2 = next(first2, length);

        if (length == 1) return *first1 == *first2;

        // 剪枝,提前返回

        int A[26]; // 每个字符的计数器

        fill(A, A + 26, 0);

        for(int i = 0; i < length; i++) A[*(first1+i)-'a']++; for(int i = 0; i < length; i++) A[*(first2+i)-'a']--; for(int i = 0; i < 26; i++) if (A[i] != 0) return false;

        for (int i = 1; i < length; ++i)

            if ((isScramble(first1, first1 + i, first2)

                 && isScramble(first1 + i, last1, first2 + i))

                || (isScramble(first1, first1 + i, last2 - i) && isScramble(first1 + i, last1, first2)))

                return true;

        return false;

    }

};

备忘录法

// LeetCode, Interleaving String

// 递归 +map cache

// 时间复杂度 O(n^3),空间复杂度 O(n^3)

class Solution {

public:

    bool isScramble(string s1, string s2) {

        cache.clear();

        return isScramble(s1.begin(), s1.end(), s2.begin());

    }

private:

    typedef string::const_iterator Iterator;

    map<tuple<Iterator, Iterator, Iterator>, bool> cache;

    bool isScramble(Iterator first1, Iterator last1, Iterator first2) {

        auto length = distance(first1, last1);

        auto last2 = next(first2, length);

        if (length == 1) return *first1 == *first2;

        for (int i = 1; i < length; ++i)

            if ((getOrUpdate(first1, first1 + i, first2)

                 && getOrUpdate(first1 + i, last1, first2 + i))

                || (getOrUpdate(first1, first1 + i, last2 - i) && getOrUpdate(first1 + i, last1, first2)))

                return true;

        return false;

    }

    

    bool getOrUpdate(Iterator first1, Iterator last1, Iterator first2) {

        auto key = make_tuple(first1, last1, first2);

        auto pos = cache.find(key);

        return (pos != cache.end()) ?

        pos->second : (cache[key] = isScramble(first1, last1, first2));

    }

};

备忘录法

typedef string::const_iterator Iterator; typedef tuple<Iterator, Iterator, Iterator> Key; // 定制一个哈希函数

namespace std {

    template<> struct hash<Key> {

        size_t operator()(const Key & x) const {

            Iterator first1, last1, first2;

            tie(first1, last1, first2) = x;

            int result = *first1;

            result = result * 31 + *last1;

            result = result * 31 + *first2;

            result = result * 31 + *(next(first2, distance(first1, last1)-1));

            return result;

        }

    };

    }

// LeetCode, Interleaving String

// 递归 +unordered_map cache, map // 时间复杂度 O(n^3),空间复杂度 O(n^3)

class Solution {

public:

    unordered_map<Key, bool> cache;

    bool isScramble(string s1, string s2) {

        cache.clear();

        return isScramble(s1.begin(), s1.end(), s2.begin());

    }

    bool isScramble(Iterator first1, Iterator last1, Iterator first2) {

        auto length = distance(first1, last1);

        auto last2 = next(first2, length);

        if (length == 1)

            return *first1 == *first2;

        for (int i = 1; i < length; ++i)

            if ((getOrUpdate(first1, first1 + i, first2)

                 && getOrUpdate(first1 + i, last1, first2 + i))

                || (getOrUpdate(first1, first1 + i, last2 - i)&& getOrUpdate(first1 + i, last1, first2)))

                return true;

        return false;

    }

    

    bool getOrUpdate(Iterator first1, Iterator last1, Iterator first2) {

        auto key = make_tuple(first1, last1, first2);

        auto pos = cache.find(key);

        return (pos != cache.end()) ?

        pos->second : (cache[key] = isScramble(first1, last1, first2));

    }

};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值