87. Scramble String
2016-09-02 20:55
253 查看
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 =
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node
string
We say that
Similarly, if we continue to swap the children of nodes
it produces a scrambled string
We say that
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
1.我的解答 好不容易写成功的哇哇~~ 最后还是超时了。。。。泪崩~~~
要对s1进行改变,然后判断s2是否存在于s1的变换集合中
我的想法就是,对字符串进行依次个切分,然后把两部分进行递归交换,把交换的都存在集合里,最后组合起来看看是不是跟s2是否相等。
比如 abcd 依次划分为a,bcd ab,cd abc,d
然后依次对各个部分递归
用dfs?? 同时记下来每个状态的变换,用记忆化搜索方法
class Solution {
public:
void solve(string s, map<string,set<string>>& sets){
map<string,set<string>> s1, s2;
if(s.size() == 1){
if(sets.find(s) == sets.end())
sets[s].insert(s);
return;
}
if(sets.find(s) != sets.end())
return;
else
sets[s].insert(s); //这里注意下,要把s本身也加入进去
for(int i = 0; i < s.size()-1; i++){
string p1 = s.substr(0,i+1);
string p2 = s.substr(i+1);
solve(p1,s1);
solve(p2,s2);
for(set<string>::iterator it = s1[p1].begin(); it != s1[p1].end(); it++){
for(set<string>::iterator is = s2[p2].begin(); is != s2[p2].end(); is++){
string t = *it + *is; //这里也要注意下,交换和不交换都要记录进去 如 a+f(bc)
sets[s].insert(t);
t = *is + *it; // f(bc)+a
sets[s].insert(t);
}
}
}
}
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size() || s1.size() == 0 || s2.size() == 0) return false;
if(s1.size() == 1){
if(s1[0] == s2[0])
return true;
else
return false;
}
map<string,set<string>> sets;
solve(s1, sets);
for(set<string>::iterator it = sets[s1].begin(); it != sets[s1].end(); it++){
if(*it == s2)
return true;
}
return false;
}
};
2. 用动态规划的方法
大神真是天才啊啊啊
解题思路: 因为这道题根本就是对s1进行中间某段的切分,因此只要从1~n-1的切分点进行遍历,然后比较s1是前i个部分和s2的前i个部分(当然还有对应的后n-i个的部分),这种情况下的对应上呢?
还是s2的后i个部分和s1的前i个部分对应上呢? 这种情况就是对s1的第i个点进行旋转了。
同时在比较以上步骤之前,先判断s1 s2两部分是否字母都相同,如果不同就直接返回false
注意点: 这里我漏了一个,就是如果s1==s2,直接就return true; 无需再进行比较;这也避免了出现空串和单个字母的情况的出现的处理了、
以下是代码:
class Solution {
public:
bool equals(string s1, string s2){//判断s1和s2中的字母是否都相同,这是最基本的判断
int c[26];
memset(c, 0, sizeof(c));
for(int i = 0; i < s1.size(); i++)
c[s1[i] - 'a']++;
for(int i = 0; i < s2.size(); i++){
c[s2[i] - 'a']--;
if(c[s2[i] - 'a'] < 0)
return false;
}
return true;
}
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size()) return false;
int n = s1.size();
if(s1 == s2) return true;
if(equals(s1, s2)){
for(int i = 1; i < s1.size(); i++){ //这个是个数
string s11 = s1.substr(0,i); //s1的前i个数
string s12 = s1.substr(i); //s1的后n-i个数
string s21 = s2.substr(0,i); //s2的前i个数
string s22 = s2.substr(i); //s2的后n-i个数
string s23 = s2.substr(n-i); //s2的后i个数
string s24 = s2.substr(0,n-i); //s2的后n-i个数
if(isScramble(s11,s21) && isScramble(s12,s22))
//假如是对s1没有旋转,就把s1,s2 对应的第i部分切开的前i个和后n-i个进行比较
return true;
if(isScramble(s11, s23) && isScramble(s12, s24)) //假如对s1进行旋转,就把s1的前i个和s2的后i个进行比较
return true;
}
}
return false;
}
};
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.
1.我的解答 好不容易写成功的哇哇~~ 最后还是超时了。。。。泪崩~~~
要对s1进行改变,然后判断s2是否存在于s1的变换集合中
我的想法就是,对字符串进行依次个切分,然后把两部分进行递归交换,把交换的都存在集合里,最后组合起来看看是不是跟s2是否相等。
比如 abcd 依次划分为a,bcd ab,cd abc,d
然后依次对各个部分递归
用dfs?? 同时记下来每个状态的变换,用记忆化搜索方法
class Solution {
public:
void solve(string s, map<string,set<string>>& sets){
map<string,set<string>> s1, s2;
if(s.size() == 1){
if(sets.find(s) == sets.end())
sets[s].insert(s);
return;
}
if(sets.find(s) != sets.end())
return;
else
sets[s].insert(s); //这里注意下,要把s本身也加入进去
for(int i = 0; i < s.size()-1; i++){
string p1 = s.substr(0,i+1);
string p2 = s.substr(i+1);
solve(p1,s1);
solve(p2,s2);
for(set<string>::iterator it = s1[p1].begin(); it != s1[p1].end(); it++){
for(set<string>::iterator is = s2[p2].begin(); is != s2[p2].end(); is++){
string t = *it + *is; //这里也要注意下,交换和不交换都要记录进去 如 a+f(bc)
sets[s].insert(t);
t = *is + *it; // f(bc)+a
sets[s].insert(t);
}
}
}
}
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size() || s1.size() == 0 || s2.size() == 0) return false;
if(s1.size() == 1){
if(s1[0] == s2[0])
return true;
else
return false;
}
map<string,set<string>> sets;
solve(s1, sets);
for(set<string>::iterator it = sets[s1].begin(); it != sets[s1].end(); it++){
if(*it == s2)
return true;
}
return false;
}
};
2. 用动态规划的方法
大神真是天才啊啊啊
解题思路: 因为这道题根本就是对s1进行中间某段的切分,因此只要从1~n-1的切分点进行遍历,然后比较s1是前i个部分和s2的前i个部分(当然还有对应的后n-i个的部分),这种情况下的对应上呢?
还是s2的后i个部分和s1的前i个部分对应上呢? 这种情况就是对s1的第i个点进行旋转了。
同时在比较以上步骤之前,先判断s1 s2两部分是否字母都相同,如果不同就直接返回false
注意点: 这里我漏了一个,就是如果s1==s2,直接就return true; 无需再进行比较;这也避免了出现空串和单个字母的情况的出现的处理了、
以下是代码:
class Solution {
public:
bool equals(string s1, string s2){//判断s1和s2中的字母是否都相同,这是最基本的判断
int c[26];
memset(c, 0, sizeof(c));
for(int i = 0; i < s1.size(); i++)
c[s1[i] - 'a']++;
for(int i = 0; i < s2.size(); i++){
c[s2[i] - 'a']--;
if(c[s2[i] - 'a'] < 0)
return false;
}
return true;
}
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size()) return false;
int n = s1.size();
if(s1 == s2) return true;
if(equals(s1, s2)){
for(int i = 1; i < s1.size(); i++){ //这个是个数
string s11 = s1.substr(0,i); //s1的前i个数
string s12 = s1.substr(i); //s1的后n-i个数
string s21 = s2.substr(0,i); //s2的前i个数
string s22 = s2.substr(i); //s2的后n-i个数
string s23 = s2.substr(n-i); //s2的后i个数
string s24 = s2.substr(0,n-i); //s2的后n-i个数
if(isScramble(s11,s21) && isScramble(s12,s22))
//假如是对s1没有旋转,就把s1,s2 对应的第i部分切开的前i个和后n-i个进行比较
return true;
if(isScramble(s11, s23) && isScramble(s12, s24)) //假如对s1进行旋转,就把s1的前i个和s2的后i个进行比较
return true;
}
}
return false;
}
};
相关文章推荐
- MyEclipse Web Project转Eclipse Dynamic Web Project
- DLL(Dynamic Linkable Library) 详解说明
- 深入C# 4.0 新特性dynamic、可选参数、命名参数的详细介绍
- C# Dynamic关键字之:解析dynamic就是Object
- C# Dynamic关键字之:dynamic为什么比反射快的详解
- Dynamic和Var的区别及dynamic使用详解
- C# dynamic关键字的使用方法
- PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
- MariaDB扩展特性--动态列
- jenkins动态参数构建
- 编程语言进化
- DHCP Snooping + Dynamic ARP Inspection(DAI) 配置
- 架设动态 DNS 服务器: 让你成为 ISP 啦
- 关于php-fpm子进程设置
- 建立C语言动态链接库
- php-fpm的max_chindren的一些误区
- NSDictionary
- hyperv 动态磁盘的缺陷
- How to Convert Dynamic Disk to Basic Disk without Losing Data?
- 五个编程语言设计的失误