• [leetcode] 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.

    https://oj.leetcode.com/problems/scramble-string/

    思路1:枚举DFS,比如要比较s1和s2,s1分成a1和b1,s2分成a2和b2,需要分别比较((a1~a2) && (b1~b2))或者 ((a1~b2) && (a1~b2))。

    思路2:DP。dp[i][j][k]表示s1从i开始k长度的字符串与s2从从j开始k长度的字符串是否是scrambled string。

    当k=1时,只需比较s1.charAt(i)是否等于s2.charAt(j)即可。

    当k>1是,需要枚举分割点,令左半边长度为l,则右边长度为k-l,(1<l<k)。对于每个l,比较((a1~a2) && (b1~b2))或者 ((a1~b2) && (a1~b2))。

    public class Solution {
        public boolean isScramble(String s1, String s2) {
            if (s1.length() != s2.length())
                return false;
            int len = s1.length();
            boolean dp[][][] = new boolean[len][len][len + 1];
    
            for (int k = 1; k <= len; k++) {
                for (int i = 0; i <= len - k; i++) {
                    for (int j = 0; j <= len - k; j++) {
                        if (k == 1)
                            dp[i][j][k] = (s1.charAt(i) == s2.charAt(j));
                        else {
                            for (int l = 1; l < k; l++) {
                                if (dp[i][j][l] && dp[i + l][j + l][k - l] || dp[i][j + k - l][l] && dp[i + l][j][k - l]) {
                                    dp[i][j][k] = true;
                                    break;
                                }
                            }
    
                        }
    
                    }
                }
            }
            return dp[0][0][len];
    
        }
    
        public static void main(String[] args) {
            System.out.println(new Solution().isScramble("great", "rgeat"));
            System.out.println(new Solution().isScramble("great", "rgtae"));
            System.out.println(new Solution().isScramble("great", "rgtta"));
    
        }
    
    }
    View Code

    第二遍参考:暴力法,注意长度为1时的判断,不要忘记了。

    public class Solution {
        public boolean isScramble(String s1, String s2) {
            int len1 = s1.length();
            int len2 = s2.length();
            if (len1 != len2)
                return false;
            if (len1 == 0)
                return true;
            if (len1 == 1)
                return s1.equals(s2);
    
            char[] c1 = s1.toCharArray();
            char[] c2 = s2.toCharArray();
    
            Arrays.sort(c1);
            Arrays.sort(c2);
            for (int i = 0; i < len1; i++) {
                if (c1[i] != c2[i])
                    return false;
            }
    
            for (int i = 1; i < len1; i++) {
                String s11 = s1.substring(0, i);
                String s12 = s1.substring(i);
                String s21 = s2.substring(0, i);
                String s22 = s2.substring(i);
                if (isScramble(s11, s21) && isScramble(s12, s22))
                    return true;
                else {
                    String s31 = s2.substring(0, len1 - i);
                    String s32 = s2.substring(len1 - i);
                    if (isScramble(s11, s32) && isScramble(s12, s31))
                        return true;
                }
            }
            return false;
    
        }
    
    
    }

    DP解法注意递推公式: if (dp[i][j][l] && dp[i + l][j + l][k - l] || dp[i][j + k - l][l] && dp[i + l][j][k - l])

    第三遍记录:

    dfs法重新写了下超时, 排序优化后就可以过了。

    import java.util.Arrays;
    
    public class Solution {
    
        public boolean isScramble(String s1, String s2) {
            //terminal condition
            int len1 = s1.length();
            int len2 = s2.length();
            if (len1 != len2)
                return false;
            if (s1.equals(s2))
                return true;
            
            //optimization
            char[] c1 = s1.toCharArray();
            char[] c2 = s2.toCharArray();
            Arrays.sort(c1);
            Arrays.sort(c2);
            for (int i = 0; i < len1; i++) {
                if (c1[i] != c2[i])
                    return false;
            }
            
            //recursion
            for (int i = 1; i < len1; i++) {
                String s11 = s1.substring(0, i);
                String s12 = s1.substring(i, len1);
                String s21 = s2.substring(0, i);
                String s22 = s2.substring(i, len2);
                if (isScramble(s11, s21) && isScramble(s12, s22))
                    return true;
                String s31 = s2.substring(0, len2 - i);
                String s32 = s2.substring(len2 - i, len2);
    
                if (isScramble(s11, s32) && isScramble(s12, s31))
                    return true;
    
            }
    
            return false;
    
        }
    
        public static void main(String[] args) {
            System.out.println(new Solution().isScramble("great", "rgeat"));
            System.out.println(new Solution().isScramble("great", "rgtae"));
            System.out.println(new Solution().isScramble("abcdefghijklmnopq", "efghijklmnopqcadb"));
    
        }
    
    }

    参考:

    http://blog.csdn.net/pickless/article/details/11501443

    http://www.blogjava.net/sandy/archive/2013/05/22/399605.html

  • 相关阅读:
    Systemd入门教程:命令篇(转)
    Systemd入门教程:实战篇(转)
    Linux守护进程的启动方法(转)
    Ubuntu 16.04安装Chrome浏览器时提示:N: 忽略‘google-chrome.list.1’(于目录‘/etc/apt/sources.list.d/’),鉴于它的文件扩展名无效
    Ubuntu 16.04使用timedatectl进行管理时间(UTC/CST)(服务器/桌面)
    Ubuntu 16.04没有/etc/default/rcS文件的UTC设置选项的问题解决
    CentOS 6.9系统时间和硬件时间设置(转)
    Ubuntu 16.04使用“从互联网自动获取”时间无法写入硬件BIOS的奇怪问题
    MySQL中in子查询会导致无法使用索引问题(转)
    MySQL性能分析及explain的使用(转)
  • 原文地址:https://www.cnblogs.com/jdflyfly/p/3819154.html
Copyright © 2020-2023  润新知