Java-使用递归将数组展平

3

我一直在练习算法,递归总是我的弱点。这个问题要求将嵌套数组压缩为一个单一的数组。如果使用循环给出一个O(n^3) [给定相同大小的3d数组]的解决方案将会很简单。

然而,我已经在苦斗几个小时了。这就是我目前拥有的,请注意,我尝试了不同的解决方案,这只是我决定留给大家发布的。

我想要两件事情,第一,是否有办法修复我的当前代码以获得正确的输出;第二,是否有更简单和更清晰的用递归编写此代码的方式,谢谢!

额外问题:如果我不知道嵌套数组的维数,我该如何使用递归解决此问题?

编辑 好吧,在一些硬编码之后(我不想这样做),我设法使这个问题得到解决。但代码现在是硬编码且非常混乱,是否有办法清理代码或使用更简单的方法使用递归解决此问题?

编辑2 我正在尝试使用辅助方法递归重新做这个问题。我会看看是否可以使用这种风格更好地解决问题。

import java.io. * ;
    import java.util. * ;
    class Solution {
    // static int oneLen = 0;
    //static int twoLen = 0;
    //static int threeLen = 0;

    static int oneCnt = 0;
            static int twoCnt = 0;
            static int threeCnt = 0;
            static ArrayList < Integer > result = new ArrayList < Integer > ();
            public static ArrayList < Integer > flatten(int [][][] arr){

    if (oneCnt < arr[threeCnt][twoCnt].length && !(oneCnt == 2 && twoCnt == 2 && threeCnt == 2))
    {


    if (oneCnt == 0 && twoCnt == 0 && threeCnt == 0){
    result.add(arr[threeCnt][twoCnt][oneCnt]);
            oneCnt++;
            result.add(arr[threeCnt][twoCnt][oneCnt]);
            System.out.println("Line One");
            System.out.println("Count1:  " + oneCnt);
            System.out.println("Count2:  " + twoCnt);
            System.out.println("Count3:  " + threeCnt);
    }
    oneCnt++;
            if (oneCnt != 3){
    result.add(arr[threeCnt][twoCnt][oneCnt]); }






    System.out.println("Line One");
            System.out.println("Count1:  " + oneCnt);
            System.out.println("Count2:  " + twoCnt);
            System.out.println("Count3:  " + threeCnt);
            flatten(arr);
    }     else if (oneCnt == arr[threeCnt][twoCnt].length && twoCnt < arr[threeCnt].length - 1){


    //oneLen = 0;    
    oneCnt = 0;
            // twoLen++;


            twoCnt++;
            result.add(arr[threeCnt][twoCnt][oneCnt]);
            System.out.println("Line Two");
            System.out.println("Count:1  " + oneCnt);
            System.out.println("Count:2  " + twoCnt);
            System.out.println("Count:3  " + threeCnt);
            flatten(arr);
    }

    else if (oneCnt == arr[threeCnt][twoCnt].length && twoCnt == arr[threeCnt].length - 1 && threeCnt < arr.length - 1){

    oneCnt = 0;
     twoCnt = 0;
            threeCnt++;
            result.add(arr[threeCnt][twoCnt][oneCnt]);
            System.out.println("Line Three");
            System.out.println("Count:1  " + oneCnt);
            System.out.println("Count:2  " + twoCnt);
            System.out.println("Count:3  " + threeCnt);
            flatten(arr);
    }
    return result;
    }
    public static void main(String[] args) {
    int[][][] array =
    {  { {1, 2, 3}, { 4, 5, 6}, { 7, 8, 9} },
    { {10, 11, 12}, {13, 14, 15}, {16, 17, 18} },
    { {19, 20, 21}, {22, 23, 24}, {25, 26, 27} } };
            flatten(array);
            for (int i = 0; i < result.size(); i++){
    System.out.print(result.get(i) + ",");
    }
    }
    }

输出:1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、

Edit3 使用递归帮助后,我几乎有了答案,但最后一个元素不会添加到ArrayList中。

import java.io. * ;
    import java.util. * ;
    class Solution {



    static ArrayList < Integer > result = new ArrayList < Integer > ();
            public static void flatten(int [][][] arr){
    int oneLen = 0;
            int twoLen = 0;
            int threeLen = 0;
            flattenHelper(arr, oneLen, twoLen, threeLen);
    }

    public static void flattenHelper(int [][][] arr, int oneLen, int twoLen, int threeLen){

    if (oneLen < arr[threeLen][twoLen].length - 1){
    System.out.println("Line One");
            System.out.println("Count:1  " + oneLen);
            System.out.println("Count:2  " + twoLen);
            System.out.println("Count:3  " + threeLen);
            result.add(arr[threeLen][twoLen][oneLen]);
            flattenHelper(arr, oneLen + 1, twoLen, threeLen);
    }
    else if (twoLen < arr[threeLen].length - 1){
    System.out.println("Line Two");
            System.out.println("Count:1  " + oneLen);
            System.out.println("Count:2  " + twoLen);
            System.out.println("Count:3  " + threeLen);
            result.add(arr[threeLen][twoLen][oneLen]);
            flattenHelper(arr, oneLen = 0, twoLen + 1, threeLen);
    }     else if (threeLen < arr.length - 1){
    System.out.println("Line Two");
            System.out.println("Count:1  " + oneLen);
            System.out.println("Count:2  " + twoLen);
            System.out.println("Count:3  " + threeLen);
            result.add(arr[threeLen][twoLen][oneLen]);
            flattenHelper(arr, oneLen = 0, twoLen = 0, threeLen + 1);
    }

    }

    public static void main(String[] args) {
    int[][][] array =
    {  { {1, 2, 3}, { 4, 5, 6}, { 7, 8, 9} },
    { {10, 11, 12}, {13, 14, 15}, {16, 17, 18} },
    { {19, 20, 21}, {22, 23, 24}, {25, 26, 27} } };
            flatten(array);
            for (int i = 0; i < result.size(); i++){
    System.out.print(result.get(i) + ",");
    }
    }
    }

输出: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26

2个回答

7

这是一个递归函数,你不需要改变输入的结构,也不需要知道数组的维度。你可以将数组、列表和其他对象混合在一起,它会返回一个ArrayList:

package stackOverflow;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

public class Solution
{
    public static void main(String[] args) {
        int[][][] int3dArray = { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
                { { 10, 11, 12 }, { 13, 14, 15 }, { 16, 17, 18 } },
                { { 19, 20, 21 }, { 22, 23, 24 }, { 25, 26, 27 }, { 28 }, { 29, 30 } } };
        String[][] string2dArray = { { "He, llo" }, { "Wo", "rld" } };
        String[] stringArray = { "Hello", "World" };
        Object[] objectArray = { "Hell", 0, "W", 0, "rld" };

        List<Object> mixList = new ArrayList<Object>();
        mixList.add("String");
        mixList.add(3);
        mixList.add(string2dArray);

        System.out.println(flatten(int3dArray));
        System.out.println(flatten(flatten(int3dArray)));
        System.out.println(flatten(3));
        System.out.println(flatten(stringArray));
        System.out.println(flatten(string2dArray));
        System.out.println(flatten(objectArray));
        System.out.println(flatten(mixList));
    }

    private static List<Object> flatten(Object object) {
        List<Object> l = new ArrayList<Object>();
        if (object.getClass().isArray()) {
            for (int i = 0; i < Array.getLength(object); i++) {
                l.addAll(flatten(Array.get(object, i)));
            }
        } else if (object instanceof List) {
            for (Object element : (List<?>) object) {
                l.addAll(flatten(element));
            }
        } else {
            l.add(object);
        }
        return l;
    }
}

它输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
[3]
[Hello, World]
[He, llo, Wo, rld]
[Hell, 0, W, 0, rld]
[String, 3, He, llo, Wo, rld]

这里有一个修改版,它可以将Map转换为值的集合,并且可以输出Set或List。

这是我的原始解决方案,只显示结果,但返回void:

package stackOverflow;

import java.lang.reflect.Array;


public class Solution
{
    public static void main(String[] args) {
        int[][][] array = { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
                { { 10, 11, 12 }, { 13, 14, 15 }, { 16, 17, 18 } },
                { { 19, 20, 21 }, { 22, 23, 24 }, { 25, 26, 27 }, { 28 } } };
        flatten(array);
    }

    private static void flatten(Object object) {
        if (object.getClass().isArray()) {
            for (int i = 0; i < Array.getLength(object); i++) {
                flatten(Array.get(object, i));
            }
        } else {
            System.out.print(object + ",");
        }
    }
}

它返回以下结果: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,


1
谢谢!这正是我所寻找的,也回答了我提出的额外问题。 - user3051442
我可以问一下 reflect 库是做什么的,它与这个解决方案有什么关联吗?我正在尝试找一些相关文档,谢谢。 - user3051442
这是一个不错的开始: https://docs.oracle.com/javase/tutorial/reflect/ 它基本上使Java变得稍微不那么“严格”,并引入了一些在Python和Ruby等语言中更常见的方法。 有时,您无法在编译时知道所有内容,并需要等待运行时。例如:我知道此对象将看起来像一个数组,它可能是int[][]或ArrayList<Integer>,我只想迭代所有元素。 - Eric Duminil

1
如果您可以将数据更改为整数数组而不是int,您可以检查传递的数组元素并递归处理数组元素,或者如果不是,则直接将它们添加到结果中。
public static ArrayList<Integer> flatten(Object [] arr) {
    ArrayList<Integer> result = new ArrayList<>();

    for (int i = 0; i < arr.length; i++) {
        if (arr[i].getClass().isArray()){
            result.addAll(flatten((Object[])arr[i]));
        } else {
            result.add((int)arr[i]);
        }
    }

    return result;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接