• 实现一个函数,判断aim是 否是str1和str2交错组成。


    问题描述:

            给定三个字符串str1、str2和aim,如果aim包含且仅包含来自str1和str2的所有字符, 而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符之间保持 原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现一个函数,判断aim是 否是str1和str2交错组成。
    【举例】

             str1="AB",str2="12"。那么"AB12"、"A1B2"、"A12B"、"1A2B"和"1AB2"等都是 str1 和 str2 的 交错组成。

    思路:

            不管使用那种思路解题,我们必须保证字符串aim的长度是字符串str1和str2两个长度之和。

            首先我们可能会想到使用快排中的merge思想。从字符串aim的头到位遍历字符,查看当前字符时str1和str2中的哪一个,相对应的指针就向后移动一个位置,若和两个字符串中指针所指的字符都不同则直接返回false。查看字符串aim的指针是否能移动到最后的位置,如能则返回true。这种思路对于str1和str2没有相同重复字符的情况下是可行的,但是对于有相同重复字符的情况就不成立了,我们可以举下面的例子进行验证。

            例:str1="aaabc"  str2="aaa31"   aim="aaa3aab1c"

    思路一:使用动态规划的思想。

            新建一张二维表dp[i][j],行从0-str1.length,每一行表示str1前缀i的长度即str1[0..i-1],列从0-str2.length,每一列表示str2前缀j长度即str2[0..j-1]。二维表dp含义是str1前缀i长度和str2前缀j长度能否交错组成aim前缀i+j长度。

            二维表第一行第一列表示str1和str2都是用前缀0长度,生成前缀0长度的aim,一定成立填入true。

            二维表第一行表示str1前缀0长度和str2前缀相应长度组成的相应前缀长度的aim,依次判断str2和aim对应字符是否相同即可,只要出现依次false,该行后序全部填入false。

            二维表第一列表示str2前缀0长度和str1前缀相应长度组成的相应前缀长度的aim,依次判断str1和aim对应字符是否相同即可,只要出现依次false,该行后序全部填入false。

            二维表的其他位置我们做出以下分析(假设目前位置为dp[i][j]),存在两种情况:1. aim[i+j-1]==str1[i-1] && dp[i-1][j]         2. aim[i+j-1]==str2[j-1] && dp[i][j-1]  。这两种情况下二维表dp[i][j]填写true,若aim[i+j-1]==str1[i-1]==str2[j-1]则dp[i-1][j]和dp[i][j-1] 满足一个也填写true,其他情况全部填写false。

    思路二:使用动态规划的空间压缩技术。

    代码:

    思路一代码

    1. public static boolean isCross1(String s1, String s2, String ai) {
    2. if (s1 == null || s2 == null || ai == null) {
    3. return false;
    4. }
    5. char[] str1 = s1.toCharArray();
    6. char[] str2 = s2.toCharArray();
    7. char[] aim = ai.toCharArray();
    8. if (aim.length != str1.length + str2.length) {
    9. return false;
    10. }
    11. boolean[][] dp = new boolean[str1.length + 1][str2.length + 1];
    12. dp[0][0] = true;
    13. for (int i = 1; i <= str1.length; i++) {
    14. if (str1[i - 1] != aim[i - 1]) {
    15. break;
    16. }
    17. dp[i][0] = true;
    18. }
    19. for (int j = 1; j <= str2.length; j++) {
    20. if (str2[j - 1] != aim[j - 1]) {
    21. break;
    22. }
    23. dp[0][j] = true;
    24. }
    25. for (int i = 1; i <= str1.length; i++) {
    26. for (int j = 1; j <= str2.length; j++) {
    27. if ((str1[i - 1] == aim[i + j - 1] && dp[i - 1][j])
    28. || (str2[j - 1] == aim[i + j - 1] && dp[i][j - 1])) {
    29. dp[i][j] = true;
    30. }
    31. }
    32. }
    33. return dp[str1.length][str2.length];
    34. }

    思路二代码

    1. public static boolean isCross2(String str1, String str2, String aim) {
    2. if (str1 == null || str2 == null || aim == null) {
    3. return false;
    4. }
    5. char[] ch1 = str1.toCharArray();
    6. char[] ch2 = str2.toCharArray();
    7. char[] chaim = aim.toCharArray();
    8. if (chaim.length != ch1.length + ch2.length) {
    9. return false;
    10. }
    11. char[] longs = ch1.length >= ch2.length ? ch1 : ch2;
    12. char[] shorts = ch1.length < ch2.length ? ch1 : ch2;
    13. boolean[] dp = new boolean[shorts.length + 1];
    14. dp[0] = true;
    15. for (int i = 1; i <= shorts.length; i++) {
    16. if (shorts[i - 1] != chaim[i - 1]) {
    17. break;
    18. }
    19. dp[i] = true;
    20. }
    21. for (int i = 1; i <= longs.length; i++) {
    22. dp[0] = dp[0] && longs[i - 1] == chaim[i - 1];
    23. for (int j = 1; j <= shorts.length; j++) {
    24. if ((longs[i - 1] == chaim[i + j - 1] && dp[j])
    25. || (shorts[j - 1] == chaim[i + j - 1] && dp[j-1])) {
    26. dp[j] = true;
    27. } else {
    28. dp[j] = false;
    29. }
    30. }
    31. }
    32. return dp[shorts.length];
    33. }
    34. public static void main(String[] args) {
    35. String str1 = "1234";
    36. String str2 = "abcd";
    37. String aim = "1a23bcd4";
    38. System.out.println(isCross1(str1, str2, aim));
    39. System.out.println(isCross2(str1, str2, aim));
    40. }

  • 相关阅读:
    Spring boot项目集成阿里云短信服务发送短信验证码
    Vue项目开发经验
    如何在 Chrome 中设置HTTP服务器?
    2022年9月2号(常用matlab图像处理函数)
    Sass/Scss、Less 是什么?
    Springboot 集成 MongoDB
    JAVA注解
    【软件与系统安全】堆溢出
    Android - 文件存储
    Git创建本地项目推送至Gitee
  • 原文地址:https://blog.csdn.net/z1171127310/article/details/127959221