Снять список в java
Мне задали этот вопрос в интервью
Учитывая гипотетический список в 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!
Я попытался придумать нерекурсивное решение, но не смог. Может ли кто-нибудь сказать, что это нерекурсивное решение может быть?
Ответы
Ответ 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]
Ответ 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 (Depth First Search) для каждого элемента в списке. Ниже приведен пример кода из 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)
Ответ 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;
}