标签:build c++ produce can bool code represent 相同 get
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
.
You can start scrambling from any binary tree legally built from s1
, but you can not rebuild another binary tree while you are scrambling to get s2
.
Example 1:
Input: s1 = "great", s2 = "rgeat"
Output: true
Explanation: As described above.
Example 2:
Input: s1 = "a", s2 = "b"
Output: false
O(n3) time
思路:
如果组成 s1 和 s2 的每种字符的数量不同, 可以直接判定为 false
, 例如样例2的 "a" 和 "b". 以及两个字符串长度不相同也可以直接返回 false
.
这道题目的重点实际上是找到构造二叉树的方式. 二叉树的构造决定了 s1
的哪些部分可以交换位置来得到新的字符串. 下面提供了多个版本算法的代码, 这里只介绍动态规划的思路:
设定状态: f[l1][r1][l2][r2]
表示是否可以由 s1
的[l1, r1]的子串攀爬得到 s2
的[l2, r2]的子串. 决策便是从哪里分割 s1
, 所以我们枚举分割的点, 于是达到了子问题.
不过需要注意的是, 由于二叉树的子节点可以被交换, 所以 s2
可能是被交换过的, 所以完整的状态转移方程是:
// 枚举k, 表示从 s1的 [l1, r1] 的第k个字符后分割, 只要有其中一种分割可以得到 s2 即可, 因此是在枚举的 k 中取 或运算
f[l1][r1][l2][r2] = OR (f[l1][l1 + k - 1][l2][l2 + k - 1] && f[l1 + k][r1][l2 + k][r2]) // 该节点的两个子节点没有交换过
OR (f[l1][l1 + k - 1][r2 - k + 1][r2] && f[l1 + k][r1][l2][r2 - k]) // 该节点的两个子节点交换过
边界状态即: f[l1][l1][l2][l2] = (s1[l1] == s2[l2])
注意到 r1 - l1 == r2 - l2, 所以这个四维数组可以被优化掉一维.
public class Solution { /** * @param s1: A string * @param s2: Another string * @return: whether s2 is a scrambled string of s1 */ HashMap<String, Boolean> hash = new HashMap<String, Boolean>(); public boolean isScramble(String s1, String s2) { // Write your code here if (s1.length() != s2.length()) return false; if (hash.containsKey(s1 + "#" + s2)) return hash.get(s1 + "#" + s2); int n = s1.length(); if (n == 1) { return s1.charAt(0) == s2.charAt(0); } for (int k = 1; k < n; ++k) { if (isScramble(s1.substring(0, k), s2.substring(0, k)) && isScramble(s1.substring(k, n), s2.substring(k, n)) || isScramble(s1.substring(0, k), s2.substring(n - k, n)) && isScramble(s1.substring(k, n), s2.substring(0, n - k))) { hash.put(s1 + "#" + s2, true); return true; } } hash.put(s1 + "#" + s2, false); return false; } }
标签:build c++ produce can bool code represent 相同 get
原文地址:https://www.cnblogs.com/FLAGyuri/p/12078279.html