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]

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java编程之设计模式之工厂方法模式全解
1 日志记录器的设计 Sunny软件公司欲开发一个系统运行日志记录器(Logger),该记录器可以通过多种途径保存系统的运行日志,如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。在设计各类日志记录器时,Sunny公司的开发人员发现需要对日志记录器进行一些初始化工作,初始化参数的设置过程较为复杂,而且某些参数的设置有严格的先后次序,否则可能会发生记录失败。如何封装记录器的初始化过程并保证多种记录器切换的灵活性是Sunny公司开发人员面临的一个难题。 Sunny公司的开发人员通过对该需求进行分析,发现该日志记录器有两个设计要点: (1) 需要封装日志记录器的初始化过程,这些初始化工作较为复杂,例如需要初始化其他相关的类,还有可能需要读取配置文件(例如连接数据库或创建文件),导致代码较长,如果将它们都写在构造函数中,会导致构造函数庞大,不利于代码的修改和维护; (2) 用户可能需要更换日志记录方式,在客户端代码中需要提供一种灵活的方式来选择日志记录器,尽量在不修改源代码的基础上更换或者增加日志记录方式。 Sunny公司开发人员最初使用简单工厂模式对日志记录器进行了...
- 下一篇
深入Spring Boot:Spring Context的继承关系和影响
前言 对于一个简单的Spring boot应用,它的spring context是只会有一个。 非web spring boot应用,context是AnnotationConfigApplicationContext web spring boot应用,context是AnnotationConfigEmbeddedWebApplicationContext AnnotationConfigEmbeddedWebApplicationContext是spring boot里自己实现的一个context,主要功能是启动embedded servlet container,比如tomcat/jetty。 这个和传统的war包应用不一样,传统的war包应用有两个spring context。参考:http://hengyunabc.github
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路