Flatten Nested Arrays(展平巢狀陣列)
這個題目是在一個公司現場面談的時候的一個題目。雖然對這種找工作上來就做題目的現象比較反感。
但是大環境如此,也只能被蹂躪了。
中文描述
題目要求比較簡單:[1,2,[3],[[4]],5,6] -> [1,2,3,4,5,6]
就是陣列中巢狀陣列,考察一個數組[1,2,[3],[[4]],5,6]。 你怎麼能夠輸出 1,2,3,4,5,6(並不要求按照順序輸出)。
這裡是一個巢狀陣列,你需要將這個陣列中的值全部取出來。
思路和點評
不清楚其他語言中這個資料結構怎麼儲存,我假設的是在 Java 中儲存的物件。
可以採用佇列的方式來實現,例如,在 Java 中儲存了整數,1, 2, 物件,[3] 為一個數組物件。
你可以先遍歷一次 List,將所有的 List 的物件都壓入佇列中,然後進行出隊。
在出隊時候,判斷物件是否為整數物件,如果是整數物件,就輸出,如果不是整數物件,然後將陣列物件繼續進行遍歷,然後壓入佇列,然後再出隊。
在這裡討論的問題比較多,還有 [[[2]5]] 這種多層巢狀的問題。
經過網站上的考古,這裡有 2 個方法可以更快的實現。1 是遞迴的方法,2 是 利用 Java 8 的 Stream 特性。
在寫測試程式碼之前,你需要明白下資料結構的定義,要不然你沒有辦法測試。在 Java 中你可以定義為物件陣列,如下:
Object[] array = {
1
,
2
,
new
Object[] {
3
,
4
,
new
Object[] {
5
,
new
Object[] {
new
Object[] {
6
} } },
7
},
8
,
9
,
10
};
然後可以利用遞迴,在對物件陣列進行遍歷的時候,如果你遇到了物件,那麼你需要再次呼叫你的方法,對物件中的內容進行遍歷,如果這個時候已經沒有物件了,可以返回第二層遍歷的結果,並且插入到上層 List 列表中。
如果你使用的 Java 8 的 Stream,你需要對 Stream 的使用和方法比較瞭解才可以。這裡也涉及到了遞迴,只是寫法有點不同罷了。
還有一個更加簡單粗暴的方法,當然我不認為這個方法是出題人希望考察的目標,在 Java 中你可以將陣列直接轉換成 String 字串進行輸出,比如說上面的物件佇列,你可以轉換為: [1, 2, [3, 4, [5, [[6]]], 7], 8, 9, 10]
字串進行輸出,然後使用 Java 的 Split 函式,進行按照逗號拆分後,然後將多餘 [ 和 ] 符號去掉,然後再將內容重新放回 List。 這個有點簡單粗暴,但是也一樣能夠達到目的。
原始碼
原始碼和有關程式碼的更新請訪問 GitHub:
測試類請參考:
程式碼思路請參考:
package com.ossez.codebank.interview.tests; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * PillPack * * <pre> * https://www.cwiki.us/display/ITCLASSIFICATION/Flatten+Nested+Arrays * </pre> * * @author YuCheng * */ public class PillPackTest { private final static Logger logger = LoggerFactory.getLogger(PillPackTest.class); List<Integer> returnList = new ArrayList<Integer>(); /** * https://www.cwiki.us/display/ITCLASSIFICATION/Flatten+Nested+Arrays * * FlattenNestedArrays */ @Test public void testFlattenNestedArrays() { logger.debug("Test FlattenNestedArrays"); Object[] array = { 1, 2, new Object[] { 3, 4, new Object[] { 5, new Object[] { new Object[] { 6 } } }, 7 }, 8, 9, 10 }; logger.debug("LOOP: {} - > {}", Arrays.deepToString(array), Arrays.toString(loopFlatten(array))); logger.debug("Java 8: {} - > {}", Arrays.deepToString(array), Arrays.toString(java8Flatten(array).toArray())); } /** * Loop And Recursive * * @param inputArray * @return * @throws IllegalArgumentException */ private static Integer[] loopFlatten(Object[] inputArray) throws IllegalArgumentException { // NULL CHECK if (inputArray == null) return null; List<Integer> flatList = new ArrayList<Integer>(); for (Object element : inputArray) { if (element instanceof Integer) { flatList.add((Integer) element); } else if (element instanceof Object[]) { // Recursive flatList.addAll(Arrays.asList(loopFlatten((Object[]) element))); } else { throw new IllegalArgumentException("Input must be an array of Integers or nested arrays of Integers"); } } return flatList.toArray(new Integer[flatList.size()]); } /** * Java 8 Stream to Flatten array. * * @param array * @return */ private static Stream<Object> java8Flatten(Object[] array) { // int[] flatInt = java8Flatten(array).mapToInt(Integer.class::cast).toArray(); return Arrays.stream(array).flatMap(o -> o instanceof Object[] ? java8Flatten((Object[]) o) : Stream.of(o)); } }
測試結果
上面程式的測試結果如下:
2018/12/27 13:39:22 DEBUG [com.ossez.codebank.interview.tests.PillPackTest] - Test FlattenNestedArrays
2018/12/27 13:39:22 DEBUG [com.ossez.codebank.interview.tests.PillPackTest] - LOOP: [1, 2, [3, 4, [5, [[6]]], 7], 8, 9, 10] - > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2018/12/27 13:39:22 DEBUG [com.ossez.codebank.interview.tests.PillPackTest] - Java 8: [1, 2, [3, 4, [5, [[6]]], 7], 8, 9, 10] - > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]