Java:使用日期排列填充二维数组或嵌套列表,允许空值和重复值仅考虑优先级(不是值)

问题描述 投票:0回答:1

我正在使用n日期进行操作,我想填写包含所有排列的nxm数组,考虑以下内容:

  • 排列的驱动因素必须是日期的优先级,而不是值
  • 允许空和重复/重复
  • 不要有重复的排列
  • 定义日期,未提供(此实施细节超出问题范围)

目前的工作:

到目前为止,我将问题分为3个一般情况:

  • 没有空值且没有重复的排列。
  • 具有空值但没有重复的排列。
  • 其余的排列(需要帮助这个)。

澄清情况的例子:

我有qazxsw poi日期对应于出生日期:qazxsw poi,qazxsw poi,qazxsw poi和4

我想知道平行宇宙的所有排列关于谁出生的人(日期值相对相关)。如果是Tim,则表明该人未出生;如果是重复,则意味着人们出生在同一天。

我把问题分成了3个部分。我还将日期表示为数字,因此我可以在数组中使用数字表示,然后我可以将这些数字转换为日期(可能是随机的,也可能是枚举值列表的一部分)。

例如,我将列出以下枚举日期:

Zoe

问题第一部分的排列(没有空值和没有重复的排列)应如下所示:

Liz

对于问题的第二部分,我们可以在前一步骤的所有排列中替换任何单个数字,并且我们仍然是一致的。示例如下:

Ben

能否帮我完成以下部分:

棘手的部分是包括重复的值,表明不止一个人出生在同一个日期。请参阅以下示例:

这表明Tim,Zoe和Liz出生的日期相同,他们比Ben年轻。

null

这表明蒂姆和佐伊出生的时间相同,他们比本年长;和本比Liz更老。

1 = 2018-01-01
2 = 2019-01-01
3 = 2020-01-01
4 = 2021-01-01

下面的两行表示Tim,Zoe和Liz出生的日期相同,并且比Ben年轻,但只有第一个是正确的,因为它以正确的顺序显示事件的优先级。

[ Tim , Zoe , Liz , Ben ]
[  1  ,  2  ,  3  ,  4  ]
[  1  ,  2  ,  4  ,  3  ]
[  1  ,  3  ,  2  ,  4  ]
[  1  ,  3  ,  4  ,  2  ]
[  1  ,  4  ,  3  ,  2  ]
[  1  ,  4  ,  2  ,  3  ]
[  2  ,  1  ,  3  ,  4  ]
  ...[16 more rows]...
[  4  ,  1  ,  2  ,  3  ]

问题的第1和第2部分的代码

[ Tim , Zoe , Liz , Ben ]
[  ␀ ,  2  ,  3  ,  4  ]
[  ␀ ,  2  ,  4  ,  3  ]
[  ␀ ,  3  ,  2  ,  4  ]
[  ␀ ,  3  ,  4  ,  2  ]
[  ␀ ,  4  ,  3  ,  2  ]
[  ␀ ,  4  ,  2  ,  3  ]
[  2  , ␀  ,  3  ,  4  ]
  ...[16 more rows]...
[  4 ,  ␀  ,  2  ,  3  ]
java recursion data-structures comparison permutation
1个回答
0
投票

我解决这个问题的方法是在2个一般情况下分解问题,每个案例都有2个变体。一般情况是:

1.排列没有重复。

[ Tim , Zoe , Liz , Ben ]
[  1  ,  1  ,  1  ,  2  ]

2.重复的排列。

[ Tim , Zoe , Liz , Ben ]
[  3  ,  3  ,  1  ,  2  ]

我决定用[ Tim , Zoe , Liz , Ben ] [ 1 , 1 , 1 , 2 ] [ 1 , 1 , 1 , 3 ] 表示public class Permuter { static void permute(List<Integer> list, int recursionNestingLevel, List<List<Integer>> results){ for (int listIndex = recursionNestingLevel; listIndex < list.size(); listIndex++){ Collections.swap(list, listIndex, recursionNestingLevel); permute(list, recursionNestingLevel + 1, results); Collections.swap(list, recursionNestingLevel, listIndex); } if (recursionNestingLevel == list.size() - 1){ results.add(new ArrayList<>(list)); } } public static void main(String[] args){ List<Integer> listForPermutation = Arrays.asList(1,2,3,4); List<List<Integer>> permutations = new ArrayList<>(); Permuter.permute(listForPermutation, 0, permutations); System.out.println("Permutations without null values and without duplicates:"); System.out.println(permutations.stream().map(list -> list.toString()).collect(Collectors.joining(System.lineSeparator()))); List<List<Integer>> permutationsWithNulls = permutations.stream().map(list -> list.stream().map(i -> i == 1 ? null : i).collect(Collectors.toList())).collect(Collectors.toList()); System.out.println("Permutations without null values and without duplicates:"); System.out.println(permutationsWithNulls.stream().map(list -> list.toString()).collect(Collectors.joining(System.lineSeparator()))); } } 值,因此以下变体:

1.1。排列没有重复但有 [ Eli , Dex , Eva ] [ 1 , 2 , 3 ] [ 1 , 3 , 2 ] [ 2 , 1 , 3 ] [ 2 , 3 , 1 ] [ 3 , 1 , 2 ] [ 3 , 2 , 1 ] 值。

    [ Eli , Dex , Eva ]
    [  1  ,  1  ,  1  ]
    [  1  ,  1  ,  2  ]
    [  1  ,  2  ,  1  ]
    [  2  ,  1  ,  1  ]
    [  2  ,  2  ,  1  ]
    [  2  ,  1  ,  2  ]
    [  1  ,  2  ,  2  ]

2.1。具有重复和null值的排列。

0

生成上述数字表示后,显示带日期的数据只需用带有日期字符串的数字替换带零的数字。

类Combinatorics.java通过在数组上运行排列来计算我称之为“优先模型”的东西。运行此类的null方法,以根据优先级生成日期的数字表示,可以根据简单的硬编码值或动态生成的值将其转换为日期。

    [ Eli , Dex , Eva ]
    [  0  ,  1  ,  2  ]
    [  0  ,  2  ,  1  ]
    [  1  ,  0  ,  2  ]
    [  1  ,  2  ,  0  ]
    [  2  ,  0  ,  1  ]
    [  2  ,  1  ,  0  ]

PrecedenceModel.java类根据将用于计算预测的所需元素数生成几个平方矩阵。

null

PermutationType.java类将用于对我们可以获得的不同排列进行分类。它的属性 [ Eli , Dex , Eva ] [ 0 , 0 , 0 ] [ 0 , 0 , 1 ] [ 0 , 1 , 0 ] [ 1 , 0 , 0 ] [ 1 , 1 , 0 ] [ 1 , 0 , 1 ] [ 0 , 1 , 1 ] 将指示矩阵是否具有我认为是“参数”值的零,因为我们可以用main值或稍后的任何其他值替换它们。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Combinatorics {

    PrecedenceModel precedenceModel;

    public Combinatorics(int elementCount) {
        this.precedenceModel = new PrecedenceModel(elementCount);
    }

    public PrecedenceModel getPrecedenceModel() {
        return precedenceModel;
    }

    /**
     * Calculates all permutations of elements given in <b>{@code array}</b> recursively
     */
    public static void permute(int[] array, int nestingLevel, Set<List<Integer>> results, Predicate<int[]> filter){

        if (nestingLevel == array.length) {
            if(filter.test(array)) {
                results.add(Arrays.stream(array).boxed().collect(Collectors.toCollection(ArrayList::new)));             
            }
            return;
        }

        permute(array, nestingLevel + 1, results, filter);

        for (int index = nestingLevel + 1; index < array.length; index++) {
            if (array[index] == array[nestingLevel]) {
                continue;
            }
            array = array.clone();
            int temp = array[index];
            array[index] = array[nestingLevel];
            array[nestingLevel] = temp;
            permute(array, nestingLevel + 1, results, filter);
        }
    }

    /**
     * Calculates all   permutations of elements given in <b>{@code array}</b> recursively
     */
    public Set<List<Integer>> getPermutations(int[] array, Predicate<int[]> filter){

        Set<List<Integer>> results = new LinkedHashSet<>();
        permute(array, 0, results, filter);
        return results;
    }

    /**
     * Calculates all permutations with repeated values based on
     * the base matrix of the precedence model's matrices
     */
    public Set<List<Integer>> getPermutationsWithRepetitions(int[][] precedenceModelMatrix, Predicate<int[]> filter){

        Set<List<Integer>> permutationsWithRepetitions = new LinkedHashSet<>();

        if(filter.test(precedenceModelMatrix[precedenceModelMatrix.length - 1])) {
            permutationsWithRepetitions.add(
                Arrays.stream(precedenceModelMatrix[precedenceModelMatrix.length - 1])
                        .boxed().collect(Collectors.toCollection(ArrayList::new)));
        }

        for (int i = 1; i < (precedenceModelMatrix.length - 1); i++) {
            for (int j = i + 1; j < precedenceModelMatrix.length; j++) {
                int array[] = precedenceModelMatrix[i].clone();
                permutationsWithRepetitions.addAll(getPermutations(array, filter));
                for (int k = 0; k < i + 1; k++) {
                    array[k] = j - i + precedenceModelMatrix[0][0];
                }
                array[j] = precedenceModelMatrix[0][0];
                permutationsWithRepetitions.addAll(getPermutations(array, filter));
            }
        }

        return permutationsWithRepetitions;
    }

    private Set<List<Integer>> getPrecedenceModel(PermutationType ... permutationTypes){
        return getPrecedenceModel((a -> true), permutationTypes);
    }

    public Set<List<Integer>> getPrecedenceModel(PermutationType permutationTypes, Predicate<int[]> filter){
        return getPrecedenceModel(filter, permutationTypes);
    }

    private Set<List<Integer>> getPrecedenceModel(Predicate<int[]> filter, PermutationType ... permutationTypes){
        Set<List<Integer>> result = new LinkedHashSet<>();

        Set<PermutationType> permTypes = new LinkedHashSet<>(Arrays.asList(permutationTypes));
        System.out.println(permTypes);
        Set<List<Integer>> simplePermutations = null;
        Set<List<Integer>> permutationsWithRepetitions = null;
        Set<List<Integer>> permutationsWithSingleParameter = null;
        Set<List<Integer>> permutationsWithParameterRepetitions = null;
        if(permTypes.contains(PermutationType.ALL_PERMUTATIONS)) {
            simplePermutations = getPermutations(getPrecedenceModel().getBaseMatrix()[0], filter);
            permutationsWithRepetitions = getPermutationsWithRepetitions(getPrecedenceModel().getBaseMatrix(), filter);
            permutationsWithParameterRepetitions = getPermutationsWithRepetitions(getPrecedenceModel().getParameterMatrix(), filter);
            permutationsWithSingleParameter = getPermutations(getPrecedenceModel().getParameterMatrix()[0], filter);

            result.addAll(simplePermutations);
            result.addAll(permutationsWithRepetitions);
            result.addAll(permutationsWithParameterRepetitions);
            result.addAll(permutationsWithSingleParameter);

            return result;
        }
        if(permTypes.contains(PermutationType.SIMPLE_PERMUTATIONS)) {
            simplePermutations = getPermutations(getPrecedenceModel().getBaseMatrix()[0], filter);
            result.addAll(simplePermutations);
        }
        if(permTypes.contains(PermutationType.PERMUTATION_WITH_REPETITIONS)) {
            permutationsWithRepetitions = getPermutationsWithRepetitions(getPrecedenceModel().getBaseMatrix(), filter);
            result.addAll(permutationsWithRepetitions);
        }
        if(permTypes.contains(PermutationType.PERMUTATION_WITH_PARAMETER_REPETITIONS)) {
            permutationsWithParameterRepetitions = getPermutationsWithRepetitions(getPrecedenceModel().getParameterMatrix(), filter);
            result.addAll(permutationsWithParameterRepetitions);
        }
        if(permTypes.contains(PermutationType.PERMUTATION_WITH_SINGLE_PARAMETER)) {
            permutationsWithSingleParameter = getPermutations(getPrecedenceModel().getParameterMatrix()[0], filter);
            result.addAll(permutationsWithSingleParameter);
        }

        return result;
    }

    public static void main(String[] args){

        Combinatorics combinatorics = new Combinatorics(3);
//      Set<List<Integer>> precedenceModelBypass = combinatorics.getPermutations(new int[] {1,2,3}, (a -> true));
//      System.out.println(ApiUtils.collectionToStringN1Dn(precedenceModelBypass));

        Set<List<Integer>> precedenceModel = combinatorics.getPrecedenceModel(
//                  PermutationType.ALL_PERMUTATIONS//3(6)
//                  ,
                    PermutationType.SIMPLE_PERMUTATIONS//3(6)
                    ,
                    PermutationType.PERMUTATION_WITH_REPETITIONS//3(7)
//                  ,
//                  PermutationType.PERMUTATION_WITH_PARAMETER_REPETITIONS//3(7)
//                  ,
//                  PermutationType.PERMUTATION_WITH_SINGLE_PARAMETER//3(6)
                    );
        System.out.println(org.apache.commons.lang3.StringUtils.repeat('-', 200));
        System.out.println("Numeric Model. Count: " + precedenceModel.size());
        System.out.println(ApiUtils.collectionToStringN1Dn(precedenceModel));
    }
}

这里有关于PrecedenceModel.java类的更多内容。此类生成的2个矩阵import java.util.LinkedHashMap; import java.util.Map; public class PrecedenceModel { private int elementCount; private int[][] baseMatrix; private int[][] parameterMatrix; public PrecedenceModel(int elementCount) { this.elementCount = elementCount; setBaseMatrix(elementCount); setParameterMatrix(elementCount); } public int getElementCount() { return elementCount; } public int[][] getBaseMatrix() { return baseMatrix; } public void setBaseMatrix(int elementCount) { baseMatrix = new int[elementCount][elementCount]; for (int i = 0; i < elementCount; i++) { for (int j = 0; j < elementCount; j++) { baseMatrix[i][j] = (j <= i) ? 1 : j + 1 - i; } } } public int[][] getParameterMatrix() { return parameterMatrix; } public void setParameterMatrix(int elementCount) { parameterMatrix = new int[elementCount][elementCount]; for (int i = 0; i < elementCount; i++) { for (int j = 0; j < elementCount; j++) { parameterMatrix[i][j] = (j <= i) ? 0 : j - i; } } } @SafeVarargs public static <T> Map<T, Integer> toMap(T ... values) { Map<T, Integer> map = new LinkedHashMap<>(values.length); for (int i = 0; i < values.length; i++) { map.put(values[i], i); } return map; } } isParameterRequired将如下所示:

null

public enum PermutationType {
    SIMPLE_PERMUTATIONS (false),
    PERMUTATION_WITH_SINGLE_PARAMETER (true),
    PERMUTATION_WITH_PARAMETER_REPETITIONS (true),
    PERMUTATION_WITH_REPETITIONS (false),
    ALL_PERMUTATIONS (true);

    private boolean isParameterRequired;

    private PermutationType(boolean isParameterRequired) {
        this.isParameterRequired = isParameterRequired;
    }
    public boolean isParameterRequired() {
        return isParameterRequired;
    }
}

baseMatrix

parameterMatrix

baseMatrix将用于计算没有[1, 2, 3, 4] [1, 1, 2, 3] [1, 1, 1, 2] [1, 1, 1, 1] 值(或参数)的日期的数字表示。 parameterMatrix将用于计算[0, 1, 2, 3] [0, 0, 1, 2] [0, 0, 0, 1] [0, 0, 0, 0] 值(或参数)的日期的数字表示。

任何矩阵的第一行用于计算所有排列而不重复。

棘手的部分来了......

倒数第二行用于计算仅重复的排列。这些行中的每一行的值将被重新调整以产生不同的优先级,并且这些结果中的每个将被置换以获得具有重复的所有可能排列的最终重新排列。例如。让我们来看看baseMatrix的第二排:

null

为了获得该行的不同优先级,我将重复元素(1,1)的优先级与每个非重复元素进行混洗。这可以通过改变以下值来完成:

parameterMatrix

第二排null的不同优先级是:

baseMatrix

然后必须计算第二行的所有不同优先级的所有排列。

最后,所有上述第二步程序也必须适用于第三行。并且由于第4行(边界情况)包含所有重复元素,因此不必对其运行任何操作。

以下奖励类只是我用来计算矩阵的过程示例以及矩阵中每行的不同优先级。

[1, 1, 2, 3] <- contains 2 repeated values

以下代码仅用于正确显示/打印结果,如果删除Combinatorics类的引用,则可以省略该代码。

 >>>>>>>
 ^  ^  v
 ^  ^  v
[1, 1, 2, 3] <- contains 2 repeated values
 ^  ^  v
 ^  ^  v
 <<<<<<<
© www.soinside.com 2019 - 2024. All rights reserved.