LeetCode第87题(扰乱字符串)

原题如下:

给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。

下图是字符串 s1 = “great” 的一种可能的表示形式。

great

/
gr eat
/ \ /
g r e at
/
a t
在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。

例如,如果我们挑选非叶节点 “gr” ,交换它的两个子节点,将会产生扰乱字符串 “rgeat” 。

rgeat

/
rg eat
/ \ /
r g e at
/
a t
我们将 "rgeat” 称作 “great” 的一个扰乱字符串。

同样地,如果我们继续将其节点 “eat” 和 “at” 进行交换,将会产生另一个新的扰乱字符串 “rgtae” 。

rgtae

/
rg tae
/ \ /
r g ta e
/
t a
我们将 "rgtae” 称作 “great” 的一个扰乱字符串。

给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。

示例 1:

输入: s1 = “great”, s2 = “rgeat”
输出: true
示例 2:

输入: s1 = “abcde”, s2 = “caebd”
输出: false

这道题确实是比较坑的,因为他打上了动态规划的标签,但是说实话 ,我连最优子结构 都找不到。。。所以只能另寻它路,同时你需要注意题中的一句话!!!“我们可以挑选任何一个非叶节点,然后交换它的两个子节点” 也就是说 任何一个大于等于2个size的串 都可以拆分成 2个部分!!!
比如 great 可以拆成 “g+reat” “gr+eat” “gre+at” “ grea+t ” 再从s2中挑选出 相同 size的串 来比较是否是扰乱子串 即可

根据上面的提示 一般都可以很快的写出答案来,但是!!!!!!!你会发现时间复杂度达不到!!!(这个时候 你需要有以下思考,
1.我是否做了很多无用功(让计算机计算了根本就没有必要的部分)
2.如果1中我没有做无用功,那么说明这个算法本身就有问题,我需要想其他的方法)
经过仔细观察,你会发现 如果 s1 被拆成 gr+eat s2 被拆成 eag +rt 的时候
其实根本就没有必要 去比较 rt是否是 gr的扰乱字符串了!!!!!!直接就return false

代码如下:

vector<int> str_hash(string &s){
		vector<int>m(30); for (int i = 0; i <= m.size() - 1; i++)m[i] = 0;
		for (int i = 0; i <= s.size() - 1; i++){
			m[s[i] - 'a']++;
		}
		return m;
	}
bool bijiao(vector<int>&a, vector<int>&b){
		if (a.size() != b.size())return false;
		for (int i = 0; i <= a.size() - 1; i++){
			if (a[i] != b[i])return false;
		}
		return true;
	}
	bool isScramble(string &s1, string &s2) {
		if (s1.size() <= 0 || s2.size() <= 0) return false;
		if (s1.size() <= 1){
			if (s1[0] == s2[0])
				return true;
			else return false;
		}
		vector<int>s1_hash = str_hash(s1);
		vector<int>s2_hash = str_hash(s2);
		if (bijiao(s1_hash, s2_hash) == false) return false;
		for (int size = 1; size <= s2.size() - 1; size++){
			string s2_x = s2.substr(0, size), s2_y = s2.substr(size, s2.size() - size);
			string s1_x = s1.substr(0, size), s1_y = s1.substr(size, s1.size() - size);
			if (isScramble(s1_x, s2_x) && isScramble(s1_y, s2_y)) return true;
			else {
				s1_x = s1.substr(s1.size() - size, size); s1_y = s1.substr(0, s1.size() - size);
				if (isScramble(s1_x, s2_x) && isScramble(s1_y, s2_y)) return true;
			}
		}
		return false;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值