• 用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的数字即可。

    后记

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

  • 相关阅读:
    Delegte的BeginInvoke
    C# socket 实现客户端连续发送数据
    Button的PerformClick()
    Invoke和BeginInvoke
    Application.DoEvents() 处理队列消息,防界面假死
    BackgroundWorker后台线程
    CF773F
    ORM框架,没必要搞那么复杂
    VS Unable to copy file
    Unbuntu auto start program
  • 原文地址:https://www.cnblogs.com/jason0529/p/13849742.html
Copyright © 2020-2023  润新知