Fork me on GitHub

用DFS解决组合问题

一直以来,大量做各类管理系统的程序员,大量的时间都在处理各类增删改查问题,对于其他的方面尤其是算法层面的涉及较少,这次就遇到一个问题。

业务场景

用户上传一份Excel,让用户选择其中的部分列头,程序对列头做两两组合,并对所有的组合取Excel表中的数据,绘制一个折线图。

问题分解

  1. 文件上传。前端使用异步插件提交文件,后台使用file接受即可。升级点在于进度条、重传、备份等
  2. 文件解析,基于POI、easyexcel等框架,都不难实现
  3. 选择列头做两两组合,典型的求组合问题,DFS的方式是通用实现方式。
  4. 组合获取数据,哈希表做key的方式,取出部分列,没难度
  5. 绘制图表,echarts、d3js、highcharts、G2 都没有太大难度

技术实现

抽象后的背景:针对两两组合,即在m列中求出所有2个的组合,可以通过双重循环完成,简单易懂。

双重循环

for(int i=0;i<arr.length;i++){
      for(int j=i+1;j<arr.length;j++){
            //...do something
            arr[i]; arr[j];      
      }
}

通用做法,基于dfs算法实现

DFS深度便利

private void dfs(int[] arr, int target,int begin, Deque<Integer> path, Set<List<Integer>> res) {
     if ( path.size()== target) {
        res.add(new ArrayList<>(path));
        return;
    }else if(begin>arr.length){
        return;
    }
    for (int i = begin; i < arr.length; i++) {
        path.add(arr[i]);
        dfs(arr,target,i+1,path,res);
        path.removeLast();
    }
}

优劣比较

方式一快速简单,上手快,缺点是没有扩展性,一旦组合数变成3、4、5,多重循环显然不合适。
方式二通用能适用各种组合数变化,只要调整target的数字即可。

后记

这是一个并不复杂的问题,但反映出算法在编码过程中的一些问题,一定要注意抽象,将个性化的业务问题抽象为技术问题,用通用的技术去解决,代码的健壮性大大提高。

posted @ 2020-10-20 23:03  龙城飞将军  阅读(208)  评论(0编辑  收藏  举报