假想面试题:现在有一串字符串2, 2, 3……,其中字符串中的数字类似于Word文档中的标题级别,最终效果是让它们按照Word文档导航窗格中的标题级别格式进行展示

一、问题

现在有一串字符串2, 2, 3, 4, 4, 3, 4, 4, 5, 5, 5, 5, 5, 3, 4, 4, 4, 4, 4, 3, 4, 4,其中字符串中的数字类似于Word文档中的标题级别,最终效果是让它们按照Word文档导航窗格中的标题级别格式进行展示,具体展示效果如下:

在这里插入图片描述

二、答案

1、依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>

2、代码

public class Test {
    
    
    public static void main(String[] args) {
    
    

        // 数据准备开始
        String numString = "2, 2, 3, 4, 4, 3, 4, 4, 5, 5, 5, 5, 5, 3, 4, 4, 4, 4, 4, 3, 4, 4";
        String[] split = numString.split(", ");
        List<Integer> list = new ArrayList<>();
        for (String s : split) {
    
    
            list.add(Integer.valueOf(s));
        }
        // 数据准备结束

        // 已处理对象集合
        List<Number> numberList = new ArrayList<>();

        // 最高级对象
        Number result = new Number();
        result.setChilds(new ArrayList<>());

        for (Integer num : list) {
    
    
            // 当前对象
            Number entity = new Number();
            entity.setNum(num);
            entity.setChilds(new ArrayList<>());

            // 获取父级对象
            Number parent = getParent(numberList, num);
            if (parent == null) {
    
    
                result.getChilds().add(entity);
            } else {
    
    
                parent.getChilds().add(entity);
            }

            // 放入集合
            numberList.add(entity);
        }

        // 数据打印
        for (Number child : result.getChilds()) {
    
    
            printNumber(child, "");
        }
    }

    /**
     * 数据打印
     *
     * @param number 对象
     * @param prefix 前缀
     **/
    private static void printNumber(Number number, String prefix) {
    
    
        System.out.println(prefix + number.getNum());
        List<Number> childs = number.getChilds();
        if (childs == null || childs.size() == 0) {
    
    
            return;
        }
        for (Number child : childs) {
    
    
            printNumber(child, prefix + "    ");
        }
    }

    /**
     * 获取父类(采用反向思维查找)
     *
     * @param numberList 对象集合
     * @param num        数字
     * @return 对象
     **/
    private static Number getParent(List<Number> numberList, Integer num) {
    
    
        if (numberList.size() == 0) {
    
    
            return null;
        }
        for (int i = numberList.size() - 1; i >= 0; i--) {
    
    
            Number number = numberList.get(i);
            if (number.getNum() < num) {
    
    
                return number;
            }
        }
        return null;
    }
}

/**
 * 数字类(存储数字和子级对象)
 */
class Number {
    
    

    private Integer num;

    private List<Number> childs;

    public Integer getNum() {
    
    
        return num;
    }

    public void setNum(Integer num) {
    
    
        this.num = num;
    }

    public List<Number> getChilds() {
    
    
        return childs;
    }

    public void setChilds(List<Number> childs) {
    
    
        this.childs = childs;
    }
}

3、结果

2
2
    3
        4
        4
    3
        4
        4
            5
            5
            5
            5
            5
    3
        4
        4
        4
        4
        4
    3
        4
        4

4、思路分析

首先创建一个Number类,然后类里面的childs属性是List<Number>,这是大多数人都可以想到的事情,问题关键在于如何让对应的序号放到对应的childs属性里面,那也就是找到当前节点的父节点,按照上面的逻辑,子节点的序号肯定大于父节点的序号,并且父节点顺序肯定在子节点的前面,并且具体子节点最近,因此我就把已经处理过的节点存储在numberList集合里面,然后采用反向思维的方式查找具体当前节点最近的父级节点

当然,如果子级节点没有父级节点,那么它就是最高级节点

三、拓展

1、反向思维

对于上面的问题,如果从正方向出发,其实很难有什么好的思路来进行实现,但是反向思维可以很好的解决该问题,所以以后遇到问题的时候,可以从反向出发来解决问题

2、引用数据类型

我把当前节点都是放在父节点的childs属性里面,我获取最终结果的时候只需要找到顶级节点就可以了,这其实就是引用数据类型起到的作用

四、实战

1、背景

公司有一个文档导入的项目,可以将docx文档进行导入,然后在页面上进行展示,在处理标题过程中,我们可以从上到下获取到所有的目录html,但是返回给前端的时候需要以目录树的方式返回,因此把这种实际情况进行抽象,其实就是上面的例子,公司项目中文档导入成功的截图如下:

在这里插入图片描述

2、实战模拟

2.1、代码

public class Test {
    
    
    public static void main(String[] args) {
    
    
        // 原始数据
        String jsonStr = "[\"<H2 id =\\\"h_f5ec3fd69a4d497ca4b33a10b3d71aa9\\\" name = \\\"h_f5ec3fd69a4d497ca4b33a10b3d71aa9\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:黑体;\\\"><span style=\\\"line-height:28.6pt;\\\">开发准备</span></H2>\",\"<H2 id =\\\"h_11533fd60df540dcb50e792873665d59\\\" name = \\\"h_11533fd60df540dcb50e792873665d59\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:黑体;\\\"><span style=\\\"line-height:28.6pt;\\\">功能说明</span></H2>\",\"<H3 id =\\\"h_e4569a42140041c98ae045603dbe103a\\\" name = \\\"h_e4569a42140041c98ae045603dbe103a\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:楷体;\\\"><span style=\\\"line-height:28.6pt;\\\">审批方案</span></H3>\",\"<H4 id =\\\"h_c6764240e50746f2bf08b93b36e868c4\\\" name = \\\"h_c6764240e50746f2bf08b93b36e868c4\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">配置文件</span></H4>\",\"<H4 id =\\\"h_df412c661a324d3d89e73e6e2144cfee\\\" name = \\\"h_df412c661a324d3d89e73e6e2144cfee\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">属性说明</span></H4>\",\"<H3 id =\\\"h_0bba1e95aa864e2b964254e5a4b13eae\\\" name = \\\"h_0bba1e95aa864e2b964254e5a4b13eae\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:楷体;\\\"><span style=\\\"line-height:28.6pt;\\\">集成接口</span></H3>\",\"<H4 id =\\\"h_f4d7e2cc579746b2b4e5476ed883e15d\\\" name = \\\"h_f4d7e2cc579746b2b4e5476ed883e15d\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">入口参数</span></H4>\",\"<H4 id =\\\"h_03fcedbe1dae4788b499dae77d05dc41\\\" name = \\\"h_03fcedbe1dae4788b499dae77d05dc41\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">相关接口</span></H4>\",\"<H5 id =\\\"h_778cdce51d214dde967f868780d0eab8\\\" name = \\\"h_778cdce51d214dde967f868780d0eab8\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">送审</span></H5>\",\"<H5 id =\\\"h_d0daa8157cd24b39a9d20b6165d2f2ec\\\" name = \\\"h_d0daa8157cd24b39a9d20b6165d2f2ec\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">同意</span></H5>\",\"<H5 id =\\\"h_40ba3e6901c8478399ffe3d4350932dc\\\" name = \\\"h_40ba3e6901c8478399ffe3d4350932dc\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">拟同意</span></H5>\",\"<H5 id =\\\"h_a4ae1d569ef94b92a57bd217ddab70d2\\\" name = \\\"h_a4ae1d569ef94b92a57bd217ddab70d2\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">不同意</span></H5>\",\"<H5 id =\\\"h_2abf049d3ba543638097170dbde425ba\\\" name = \\\"h_2abf049d3ba543638097170dbde425ba\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">收回</span></H5>\",\"<H3 id =\\\"h_a484ff6248dc4b3486f5716ed5116b82\\\" name = \\\"h_a484ff6248dc4b3486f5716ed5116b82\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:楷体;\\\"><span style=\\\"line-height:28.6pt;\\\">应用案例</span></H3>\",\"<H4 id =\\\"h_6fbc18ae698c43508bfe0894ec441b8f\\\" name = \\\"h_6fbc18ae698c43508bfe0894ec441b8f\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">送审</span></H4>\",\"<H4 id =\\\"h_81e4902a4db746df87823635a588dcc1\\\" name = \\\"h_81e4902a4db746df87823635a588dcc1\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">同意</span></H4>\",\"<H4 id =\\\"h_adccf8ec1c9f41fd9f2e8a3c4dfa4958\\\" name = \\\"h_adccf8ec1c9f41fd9f2e8a3c4dfa4958\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">拟同意</span></H4>\",\"<H4 id =\\\"h_04c7c25c2edb4a5ca083cf50099d5768\\\" name = \\\"h_04c7c25c2edb4a5ca083cf50099d5768\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">不同意</span></H4>\",\"<H4 id =\\\"h_1273a45625e64b07b680ae66ca7160fc\\\" name = \\\"h_1273a45625e64b07b680ae66ca7160fc\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">收回</span></H4>\",\"<H3 id =\\\"h_b7455f2532254807bbdd36a08b3e587a\\\" name = \\\"h_b7455f2532254807bbdd36a08b3e587a\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:楷体;\\\"><span style=\\\"line-height:28.6pt;\\\">数据展示</span><span style=\\\"line-height:28.6pt;\\\">的接口</span></H3>\",\"<H4 id =\\\"h_4961ecfa9f7a4a95b6d6abf8f0d3a62c\\\" name = \\\"h_4961ecfa9f7a4a95b6d6abf8f0d3a62c\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">待提交</span></H4>\",\"<H4 id =\\\"h_9f16c84cc0e1451182b1487237906282\\\" name = \\\"h_9f16c84cc0e1451182b1487237906282\\\" style=\\\"mso-line-height-rule:exactly;line-height:28.6pt;font-size:21px;font-family:仿宋;\\\"><span style=\\\"line-height:28.6pt;\\\">已提交</span></H4>\"]";
        // 数据转换
        List<String> list = JSONObject.parseArray(jsonStr, String.class);
        // 存储最高级节点的集合
        List<Catalog> resultList = new ArrayList<>();
        // 存放已处理节点集合
        List<Catalog> catalogList = new ArrayList<>();
        for (String html : list) {
    
    
            // 获取id,用作前端锚点跳转
            String id = getId(html);

            // 获取目录名称
            String caption = getCaption(html);

            // 获取目录序号
            Integer num = getNum(html);

            // 创建当前对象
            Catalog entity = new Catalog();
            entity.setId(id);
            entity.setCaption(caption);
            entity.setNum(num);

            // 获取父级对象
            Catalog parent = getParent(catalogList, num);
            if (parent == null) {
    
    
                // 最高等级数据插入
                resultList.add(entity);
            } else {
    
    
                // 判断父级childs属性是否有值
                List<Catalog> childs = parent.getChilds();
                if (childs == null) {
    
    
                    parent.setChilds(new ArrayList<>());
                }
                // 数据插入
                parent.getChilds().add(entity);
            }

            // 放入集合
            catalogList.add(entity);
        }

        // 打印目录树
        System.out.println(JSONObject.toJSONString(resultList));
    }

    /**
     * 获取父级节点对象
     *
     * @param catalogList 已处理节点集合
     * @param num         目录序号
     * @return 父级节点对象
     */
    private static Catalog getParent(List<Catalog> catalogList, Integer num) {
    
    
        if (catalogList.size() == 0) {
    
    
            return null;
        }
        for (int i = catalogList.size() - 1; i >= 0; i--) {
    
    
            Catalog catalog = catalogList.get(i);
            if (catalog.getNum() < num) {
    
    
                return catalog;
            }
        }
        return null;
    }

    /**
     * 获取id,用作前端锚点跳转
     *
     * @param html 目录Html
     * @return id值
     */
    private static String getId(String html) {
    
    
        // ?<=和?=的使用,可以看博客:https://blog.csdn.net/qq_42449963/article/details/124988267
        String pattern = "(?<=id =\").*?(?=\")";
        Matcher matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(html);
        while (matcher.find()) {
    
    
            String id = matcher.group();
            return id;
        }
        return null;
    }

    /**
     * 获取目录标题
     *
     * @param html 目录Html
     * @return 目录标题
     */
    private static String getCaption(String html) {
    
    
        if (html != null) {
    
    
            return html.replaceAll("<p.*?>|</p>|<span.*?>|<span>|</span>|<H[1-9].*?>|</H[1-9]>", "");
        }
        return null;
    }

    /**
     * 获取目录序号
     *
     * @param html 目录Html
     * @return 目录Html
     */
    private static Integer getNum(String html) {
    
    
        String pattern = "(?<=<H).*?(?= id)";
        Matcher matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(html);
        while (matcher.find()) {
    
    
            String group = matcher.group();
            Integer num = Integer.valueOf(group);
            return num;
        }
        return null;
    }
}

/**
 * 目录
 */
class Catalog {
    
    

    // id
    private String id;

    // 标题
    private String caption;

    // 序号
    private Integer num;

    private List<Catalog> childs;

    public Integer getNum() {
    
    
        return num;
    }

    public void setNum(Integer num) {
    
    
        this.num = num;
    }

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getCaption() {
    
    
        return caption;
    }

    public void setCaption(String caption) {
    
    
        this.caption = caption;
    }

    public List<Catalog> getChilds() {
    
    
        return childs;
    }

    public void setChilds(List<Catalog> childs) {
    
    
        this.childs = childs;
    }
}

2.2、结果

建议数据格式化之后再看,格式化网站:https://www.bejson.com/json/format/

扫描二维码关注公众号,回复: 14227208 查看本文章
[{
    
    "caption":"开发准备","id":"h_f5ec3fd69a4d497ca4b33a10b3d71aa9","num":2},{
    
    "caption":"功能说明","childs":[{
    
    "caption":"审批方案","childs":[{
    
    "caption":"配置文件","id":"h_c6764240e50746f2bf08b93b36e868c4","num":4},{
    
    "caption":"属性说明","id":"h_df412c661a324d3d89e73e6e2144cfee","num":4}],"id":"h_e4569a42140041c98ae045603dbe103a","num":3},{
    
    "caption":"集成接口","childs":[{
    
    "caption":"入口参数","id":"h_f4d7e2cc579746b2b4e5476ed883e15d","num":4},{
    
    "caption":"相关接口","childs":[{
    
    "caption":"送审","id":"h_778cdce51d214dde967f868780d0eab8","num":5},{
    
    "caption":"同意","id":"h_d0daa8157cd24b39a9d20b6165d2f2ec","num":5},{
    
    "caption":"拟同意","id":"h_40ba3e6901c8478399ffe3d4350932dc","num":5},{
    
    "caption":"不同意","id":"h_a4ae1d569ef94b92a57bd217ddab70d2","num":5},{
    
    "caption":"收回","id":"h_2abf049d3ba543638097170dbde425ba","num":5}],"id":"h_03fcedbe1dae4788b499dae77d05dc41","num":4}],"id":"h_0bba1e95aa864e2b964254e5a4b13eae","num":3},{
    
    "caption":"应用案例","childs":[{
    
    "caption":"送审","id":"h_6fbc18ae698c43508bfe0894ec441b8f","num":4},{
    
    "caption":"同意","id":"h_81e4902a4db746df87823635a588dcc1","num":4},{
    
    "caption":"拟同意","id":"h_adccf8ec1c9f41fd9f2e8a3c4dfa4958","num":4},{
    
    "caption":"不同意","id":"h_04c7c25c2edb4a5ca083cf50099d5768","num":4},{
    
    "caption":"收回","id":"h_1273a45625e64b07b680ae66ca7160fc","num":4}],"id":"h_a484ff6248dc4b3486f5716ed5116b82","num":3},{
    
    "caption":"数据展示的接口","childs":[{
    
    "caption":"待提交","id":"h_4961ecfa9f7a4a95b6d6abf8f0d3a62c","num":4},{
    
    "caption":"已提交","id":"h_9f16c84cc0e1451182b1487237906282","num":4}],"id":"h_b7455f2532254807bbdd36a08b3e587a","num":3}],"id":"h_11533fd60df540dcb50e792873665d59","num":2}]

猜你喜欢

转载自blog.csdn.net/qq_42449963/article/details/124984944