代码之家  ›  专栏  ›  技术社区  ›  wannaBeDev

创建具有预定义条件的字符串

  •  2
  • wannaBeDev  · 技术社区  · 12 月前

    java中是否有与正则表达式相反的东西?

    我的任务是:给定一个字符串的定义总长度,并且每个位置只能由预定义的特定字符组成,生成所有可能的字符串。

    举个例子:我想创建所有长度为3的刺,其中位置定义为

    [ABC][123][XYZ]
    

    这意味着第一个位置只能是 A, B or C ,第二个位置是数字之一 1 to 3 依此类推。因此,有效字符串为

    A1X 
    A1Y 
    A1Z 
    A2X 
    A2Y 
    A2Z 
    ...
    ... 
    C3Z 
    

    对于长度三,我当然可以使用嵌套循环。我的问题是,我事先不知道字符串的长度,也不知道每个位置有多少有效字符。有什么想法吗?

    长度为3,每个位置为3个可能字符的代码:

    public static void main(String[] args) {
        String[] first  = {"A", "B", "C"};
        String[] second = {"1", "2", "3"};
        String[] third  = {"X", "Y", "Z"};
    
        List<String> result = createStrings(first, second, third);
    
        result.forEach(System.out::println);
    }
    
    static List<String> createStrings(String[] ... strs) {
        String[] first  = strs[0];
        String[] second = strs[1];
        String[] third  = strs[2];
    
        List<String> result = new ArrayList<>();
        for (int i = 0; i < first.length; i++) {
            for (int j = 0; j < second.length; j++) {
                for (int k = 0; k < third.length; k++) {
                    result.add(first[i] + second[j] + third[k]);
                }
            }
        }
        return result;
    }
    

    我需要一些灵活的东西,它适用于所有输入。或者一种根据 strs.length 它定义了我需要多少个循环。

    2 回复  |  直到 12 月前
        1
  •  2
  •   user24714692    12 月前

    您可以使用递归:

    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            String[] first = { "A", "B", "C" };
            String[] second = { "1", "2", "3" };
            String[] third = { "X", "Y", "Z" };
            String[] fourth = { "K", "L", "M" };
            String[] fifth = { "7", "8", "9" };
    
            List<String> result = createStrings(first, second, third, fourth, fifth);
    
            result.forEach(System.out::println);
        }
    
        static List<String> createStrings(String[]... strs) {
            List<String> res = new ArrayList<>();
            getStrings(0, "", res, strs);
            return res;
        }
    
        static void getStrings(int level, String curr, List<String> res, String[]... strs) {
            if (level == strs.length) {
                res.add(curr);
                return;
            }
    
            for (String ch : strs[level]) {
                getStrings(level + 1, curr + ch, res, strs);
            }
        }
    }
    
    

    打印

    A1XK7
    A1XK8
    A1XK9
    A1XL7
    A1XL8
    A1XL9
    A1XM7
    ...
    
    C3ZK9
    C3ZL7
    C3ZL8
    C3ZL9
    C3ZM7
    C3ZM8
    C3ZM9
    

    字符串的树级构造:

    
                                  ""
                                /  |  \
                              A    B    C
                             /|\  /|\  /|\
                           1 2 3 1 2 3 1 2 3
                          /|\ /|\ /|\ /|\ /|\
                         X Y Z X Y Z X Y Z X Y Z
                        /|\/|\/|\/|\/|\/|\/|\/|\
                       K L M K L M K L M K L M K L M
                      /|\/|\/|\/|\/|\/|\/|\/|\/|\/|\
                     ... ... ... ... ... ... ... ... 
    
    • 在这个例子中,我们有五个级别。我们希望通过使用当前数组递归连接每个字符(来自每个级别)来生成所有可能的字符组合( strs[level] )然后转到下一个级别。

    • 最初,我们称 createStrings() 使用所有五个数组,它调用 getStrings(0, "", res, strs) .

    以下是递归堆栈:

    第一级(级别=0):

    • 用curr=“A”、curr=”B”、curl=“C”调用

    第二级(级别=1):

    • 对于curr=“A”:用curr=”A1“、curr=(A2)、curr=“A3”调用
    • 对于curr=“B”:使用curr=”B1“、curr==”B2“、curl=”B3“调用
    • 对于curr=“C”:使用curr=”C1“、curr==”C2“、curl=”C3“调用

    第三级(级别=2):

    • 对于curr=“A1”:用curr=”A1X“、curr=(A1Y)、curr=“A1Z”调用
    • 对于curr=“A2”:用curr=”A2X“,curr=(A2Y)”,curl=“A2Z”调用
    • 对于curr=“A3”:用curr=”A3X“、curr=(A3Y)”、curl=(A3Z)调用
    • ...

    第四级(级别=3):

    • 对于curr=“A1X”:使用curr=”A1XK“、curr=”A1XL“、curl=”A1XM“进行调用
    • 对于curr=“A1Y”:使用curr=”A1YK“、curr=”A1YL“、curl=”A1YM“进行调用
    • 对于curr=“A1Z”:用curr=”A1ZK“,curr=(A1ZL)”,curr=“A1ZM”调用
    • ...

    第五级(级别=4):

    • 对于curr=“A1XK”:使用curr=”A1XK7“、curr==”A1XK8“、curl=”A1YK9“进行调用
    • 对于curr=“A1XL”:用curr=”A1XL7“、curr=(A1XL8)、curr=“A1XL9”调用
    • 对于curr=“A1XM”:使用curr=”A1XM7“、curr=(A1XM8)、curr=“A1XM9”进行调用

    ...


    让我们在递归堆栈中跟踪一条路径:

    • 第一次呼叫: getStrings(0,“”,res,strs) ,个电话 getStrings(1, "A", res, strs) ;
    • 第二次通话: getStrings(1,“A”,res,strs) ,个电话 getStrings(2, "A1", res, strs) ;
    • 第三次通话: getStrings(2,“A1”,res,strs) ,个电话 getStrings(3, "A1X", res, strs) ;
    • 第四次呼叫: getStrings(3,“A1X”,res,strs) ,个电话 getStrings(4, "A1XK", res, strs) ;
    • 第五次通话: getStrings(4,“A1XK”,res,strs) ,个电话 getStrings(5, "A1XK7", res, strs) ; 和
    • 基本情况: getStrings(5,“A1XK7”,res,strs) ,将“A1XK7”添加到 res .
        2
  •  2
  •   Gilbert Le Blanc    12 月前

    列出多个字符数组的所有组合的一种方法是创建一个计数器,对各种可能性进行计数。

    该代码创建 int 数字数组和 int 极限数组。我们通过数字数组进行计数,直到达到每个位置的极限。然后将该数字重置为零,并递增下一个数字。

    像这样(假设每个字符数组有三种可能性):

    000
    001
    002
    010
    011
    ...
    

    以下是完整的可运行代码。

    import java.util.ArrayList;
    import java.util.List;
    
    public class CreateStrings {
    
        public static void main(String[] args) {
            String[] first = { "A", "B", "C" };
            String[] second = { "1", "2", "3", "4" };
            String[] third = { "X", "Y", "Z" };
    
            List<String> result = createStrings(first, second, third);
            result.forEach(System.out::println);
        }
    
        private static List<String> createStrings(String[]... strs) {
            List<String> strings = new ArrayList<>();
            int[] digits = new int[strs.length];
            int[] limits = new int[strs.length];
            for (int index = 0; index < strs.length; index++) {
                limits[index] = strs[index].length;
            }
    
            boolean inProcess = true;
            while (inProcess) {
                String s = "";
                for (int index = 0; index < digits.length; index++) {
                    s += strs[index][digits[index]];
                }
    //          System.out.println(s);
                strings.add(s);
    
                for (int index = digits.length - 1; index >= 0; index--) {
                    digits[index]++;
                    if (digits[index] >= limits[index]) {
                        if (index == 0) {
                            inProcess = false;
                        }
                        digits[index] = 0;
                    } else {
                        break;
                    }
                }
            }
    
            return strings;
        }
    
    }