【问题标题】:Flatten out a list in java在java中展平列表
【发布时间】:2015-09-06 04:14:21
【问题描述】:

面试时被问到这个问题

给定一个 java 中的假设列表,同时持有整数 内容,也可能包含另一个类似类型的列表

示例:[1,3,5,[6,7],8,9,10,[11,13,15,[16,17,[18,19]]],20]

输出应该是:

[1,3,5,6,7,8,9,10,11,13,15,16,17,18,19,20]

我想容易!所以我提出了一个解决问题的递归解决方案!还是不行?

面试官说子列表可能会下降到任何深度,因此可能会导致 stackoverflow 错误!

我尝试想出一个非递归的解决方案,但不能。谁能说出那个非递归解决方案可能是什么?

【问题讨论】:

  • 这个列表是如何存储的?
  • 使用递归代码,如果递归太深,您总是有可能发生堆栈溢出,但这实际上只是在这种情况下理论上的可能性 - 您必须有一个 very i> 在实践中获得 SOE 之前,深度嵌套列表(数千层?)。
  • @PM77-1 好吧,它是一个java 中的假设列表。我不确定它是如何存储的,可能是List<Object> 并使用typeof 检查正确的类型是Integer 还是List<Object>(再次)。
  • 子列表可能会下降到任何深度,因此可能导致 stackoverflow 错误! 好吧,增加堆栈的大小并收工。说真的,除非你有一些讨厌的数据,否则这不应该发生。
  • @Ouney 您似乎对有两个术语堆栈感到困惑。一种是程序使用的数据结构,它是在堆上分配的。另一个是程序的堆栈,递归调用在其上创建单独的框架。当您超过第二个堆栈的大小时,就会发生堆栈溢出。

标签: java algorithm list


【解决方案1】:

您可以将 LinkedList 用作堆栈。

public static List<Object> flattenNonRecursive(List<Object> list) {
    List<Object> result = new ArrayList<>();
    LinkedList<Object> stack = new LinkedList<>(list);
    while (!stack.isEmpty()) {
        Object e = stack.pop();
        if (e instanceof List<?>)
            stack.addAll(0, (List<?>)e);
        else
            result.add(e);
    }
    return result;
}

public static List<Object> list(Object... args) {
    return Arrays.asList(args);
}

public static void main(String[] args) {
    List<Object> list = list(1, 3, 5, list(6, 7), 8, 9, 10, list(11, 13, 15, list(16, 17, list(18, 19))), 20);
    System.out.println("flatten=" + flattenNonRecursive(list));
}

结果

flatten=[1, 3, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 20]

【讨论】:

  • 这是一个不错的解决方案。一个迂腐的注释:LinkedList 被用作 stack,而不是队列。另请查看ArrayDeque,它提供 pushpop 方法,并且在这样使用时通常优于 Stack 和 LinkedList 类。
  • 不错的解决方案!
  • @dnault 我明白你在说什么,但是将列表的内容添加到 ArrayDeque 的第 0 个索引可能有点麻烦
【解决方案2】:

这是一个迭代 Java 实现(部分基于 sarvesh 的回答):

import java.util.*;

import static java.util.Arrays.asList;

public class Main {
    public static void main(String[] ars) {
        List<Object> list = asList(asList(1, 2), 3, 4, asList(5, asList(6, 7)));

        System.out.println(flatten(list));
    }

    public static List<Integer> flatten(Iterable<Object> list) {
        List<Integer> result = new ArrayList<Integer>();
        Deque<Iterator> deque = new ArrayDeque<Iterator>();
        deque.add(list.iterator());

        while (!deque.isEmpty()) {
            Iterator it = deque.pop();

            while (it.hasNext()) {
                Object obj = it.next();
                if (obj instanceof Iterable) {
                    deque.push(it);
                    it = ((Iterable) obj).iterator();
                } else if (obj instanceof Integer) {
                    result.add((Integer) obj);
                }
            }
        }
        return result;
    }

}

【讨论】:

    【解决方案3】:

    您可以对列表中的每个元素使用 DFS(深度优先搜索)过程。以下是来自 wiki 的示例代码

    1  procedure DFS-iterative(G,v):
    2      let S be a stack
    3      S.push(v)
    4      while S is not empty
    5            v = S.pop() 
    6            if v is not labeled as discovered:
    7                label v as discovered
    8                for all edges from v to w in G.adjacentEdges(v) do
    9                    S.push(w)
    

    【讨论】:

    • 典型的 dfs 解决方案不是也总是递归的吗? dfs 的非递归版本等待二叉树?
    • 貌似,但是可以非递归写,en.wikipedia.org/wiki/Depth-first_search
    • dfs 可以是非递归的,dfs(像任何搜索一样)将形成一棵树,但它很少是二元的
    【解决方案4】:

    你可以使用下面的算法

        public List<?> flatten(List<?> source) {
            List<?> currentSource = source;
            List<Object> flattenedList = new ArrayList<Object>();
            boolean loop = true;
            while (loop) {
                loop = false;
                for (Object item : currentSource) {
                    if (item instanceof Collection<?>) {
                        flattenedList.addAll((Collection<?>) item);
                        loop = true;
                    } else {
                        flattenedList.add(item);
                    }
                }
                if (loop) {
                    currentSource = flattenedList;
                    flattenedList = new ArrayList<Object>();
                }
            }
    
            return flattenedList;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      相关资源
      最近更新 更多