[LeetCode][Java] 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 if s2 is a scrambled string of s1.

题意:

给定字符串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" and "at",这将产生一个拼凑字符"rgtae".

    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a
我们将"rgtae"称为"great"的相似字符串。

给定两个长度相等的字符串s1和s2,判定s2是否为s1的相似字符串。


算法分析:

    * 对付复杂问题的方法是从简单的特例来思考,从而找出规律。
    * 先考察简单情况:
    * 字符串长度为1:很明显,两个字符串必须完全相同才可以。
    * 字符串长度为2:当s1="ab", s2只有"ab"或者"ba"才可以。
    * 对于任意长度的字符串,我们可以把字符串s1分为a1,b1两个部分,s2分为a2,b2两个部分,满足((a1~a2) && (b1~b2))或者 ((a1~b2) && (a2~b1))


    * 如此,我们找到了解决问题的思路。首先我们尝试用递归来写。


    (递归):
    * 两个字符串的相似的必备条件是含有相同的字符集。简单的做法是把两个字符串的字符排序后,然后比较是否相同。
    * 加上这个检查就可以大大的减少递归次数。


AC代码:

<span style="font-family:Microsoft YaHei;font-size:12px;">public class Solution 
{
	public boolean isScramble(String s1, String s2) 
	{
        int l1 = s1.length();
        int l2 = s2.length();
        if(l1!=l2)
        {
            return false;
        }
        if(l1==0)
        {
            return true;
        }
        
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();
        if(l1==1)
        {
            return c1[0]==c2[0];
        }
        Arrays.sort(c1);
        Arrays.sort(c2);
        for(int i=0;i<l1;++i)
        {
            if(c1[i]!=c2[i])
                return false;
        }
        
        boolean result = false;
        for(int i=1;i<l1 && !result;++i)
        {
            String s11 = s1.substring(0,i);
            String s12 = s1.substring(i);
            String s21 = s2.substring(0,i);
            String s22 = s2.substring(i);
            result = isScramble(s11,s21) && isScramble(s12,s22);
            if(!result)
            {
                String s31 = s2.substring(0,l1-i);
                String s32 = s2.substring(l1-i);
                result = isScramble(s11,s32) && isScramble(s12,s31);
            }
        }
        return result;
    }
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值