【问题标题】:Recursively creating strings from 2 dimensional character array从二维字符数组递归创建字符串
【发布时间】:2017-07-07 18:00:11
【问题描述】:

我需要从二维数组创建所有可能的字符串,以便第一个字符来自charArray[0],第二个字符来自charArray[1]...最后一个字符来自charArray[keyLength-1]

例子:

输入:

char[][] charArray =  
{{'m','M','L','S','X'}
 {'e','E','o','N','Z'}
 {'o','G','F','r','Y'}
 {'D','H','I','J','w'}};

输出:

{meoD, meoH, meoI,..., XZYJ, XZYw}  //in an Array or ArrayList

我有一个可行的解决方案,它以@​​987654326@ 中的每个字符为根构建一棵树,并进行了深度优先的字符串构造,但 JVM 的 charArray 长度小于 12 时内存不足。我通常会采用迭代方法,但 charArray 长度(即密钥字符串长度)是在运行时决定的,我想找到一个比在密钥字符串长度上编写 switch 语句并手动写出有限数量的密钥字符串长度的循环更完整的解决方案.

我被困在程序的这一小部分上的时间比我想承认的要长,因此我们将不胜感激任何帮助!

【问题讨论】:

  • 把代码放在这里就很容易理解了。
  • 即使 charArray 是在运行时确定的,你也有数组的 .length 字段
  • @hhafeez 是的,但问题来自尝试处理数组中的字符。我能想到的最佳迭代解决方案需要最终嵌套循环内的行看起来像:keyArrayList.add(charArray[0].charAt(a)+charArray[1].charAt(b)+....+ charArray(keyLength-1).charAt(x)。也就是说我需要为每个charArray[i]手动编写一个charAt语句。如果charArray的长度变化很大,这显然会出现问题。如果你能想到一种不同的方式,我很高兴听到它。
  • @Leozeo。我很乐意详细说明任何事情以使事情更清楚,但我的程序总共大约 1000 行,所以发布整个内容似乎有点矫枉过正。在递归算法的代码方面,恐怕递归设计的可视化一直是我的一个弱点,所以我来到这里希望找到可以给我一些指点的人。该程序的目的是解决仅给定加密的 base 64 字符串的重复密钥 XOR 密码。一般来说,这是我的程序所做的:(在下一条评论中)
  • @Leozeo。 1. 使用汉明距离、重合指数、三元组和这些测试的最大公约数来检测最可能的密钥长度。 2. 将输入字符串分成大小为“key length”的块。 3. 重新排列块,这样我就有了一个包含每个块的所有第一个字符的块,一个包含每个块的所有第二个字符的块,依此类推。 4. 将每个块求解为单字符异或。 5. 对于每个块,使用卡方字符频率分析得分最高的字符很可能是该块的关键。

标签: java recursion multidimensional-array


【解决方案1】:

解决方法如下:

import java.util.ArrayList;
import java.util.List;

public class Arrays2D {

public static void main(String[] args) {
    //input keys

    String[][] charArray = 
        {{"m","M","L","S","X"},
         {"e","E","o","N","Z"},
         {"o","G","F","r","Y"},
         {"D","H","I","J","w"}};
    //print output
    System.out.println(findCombinations(charArray));

}

private static List<String> findCombinations(String[][] charArray) {
    List<String> prev = null;
    for (int i = 0; i < charArray.length; i++) {
        List<String> curr = new ArrayList<String>();
        for (int j = 0; j < charArray[i].length; j++) {
            if (i + 1 < charArray.length) {
            for (int l = 0; l < charArray[i+1].length; l++) {
                    String s = charArray[i][j] + charArray[i + 1][l];
                    curr.add(s);
                }
            }

        }
        if (prev != null && !curr.isEmpty()) {
            prev = join(prev, curr);
        }
        if (prev == null)
            prev = curr;

    }

    return prev;
}

public static List<String> join(List<String> p, List<String> q) {
    List<String> join = new ArrayList<String>();
    for (String st1 : p) {
        for (String st2 : q) {

            if (st1.substring(st1.length() - 1).equals(st2.substring(0, 1))) {
                String s = st1 + st2;
                s = s.replaceFirst(st1.substring(st1.length() - 1), "");
                join.add(s);
            }

        }
    }

    return join;
}
}

我已经检查并正确生成了组合。您可以运行并查看输出。

【讨论】:

  • 你是最棒的!非常感谢您花时间解决这个问题。如果您不介意,请您帮助我了解您的加入方法的 IF 部分。对我来说,它仍然像魔法一样。
  • 仅供将来阅读此内容的任何人参考:由于“[”和“]”是 charArray 中可能的字符,我发现我需要在 join() 中的 If 语句中添加额外的 if 语句以便分别处理。即 if(st1.substring(st1.length() - 1).equals("[")){ s = s.replaceFirst("\[", ""); } else if(st1.substring(st1.length() - 1).equals("]")){ s = s.replaceFirst("\]", ""); } else{ s = s.replaceFirst(st1.substring(st1.length() - 1), ""); } 加入。添加(S);抱歉格式化
  • 是的,我也可以解释。同时,如果对您有帮助,您会接受答案吗?
  • if 语句是连接数组的两个元素的实际条件。这表示如果 str1 的结束字符等于 str2 的第一个字符,那么它们应该被连接起来。即“cs”,“st”应该被加入,加入后我们我会扔掉加入角色s一次。所以加入cs和sc后我应该有“cst”。
猜你喜欢
  • 1970-01-01
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
相关资源
最近更新 更多