BFS与DFS

作者: 未央不了 | 来源:发表于2019-11-08 23:49 被阅读0次

1.什么是BFS,DFS

BFS宽度优先搜索.一层一层搜索.把每行的结果存入到队列中,然后遍历求下一层.
DFS深度优先搜索.第一次先到达最深,类似于栈的操作,然后弹起找完的一个节点找这个节点的下一层.
其实两种算法都是全局的遍历,时间复杂度一样的.但空间复杂度DFS小跟多.O(n)n为图的深度,BFS的空间复杂度是跟时间复杂度一样.指数级别.当然DFS肯定也是有缺点的,一个就是要用到递归.可能会因为栈的深度不够,堆栈溢出oom;而且宽度优先的话,可以搜索最短路径

2.例子:求二叉树最小深度

public int getMinDeep(TreeNode treeNode) {
        List<TreeNode> curNodes = new LinkedList<>();
        if (treeNode != null) {
            curNodes.add(treeNode);
        } else {
            return 0;
        }
        int path = 1;
        while (curNodes.size() > 0) {
    //每层用list存储,每次遍历当前层
            List<TreeNode> tempNodes = new LinkedList<>();
            for (TreeNode node : curNodes) {
    //遇到一个没有子节点了,则为最短路径
                if (node.left == null && node.right == null) {
                    return path;
                }
                if (node.left != null) tempNodes.add(node.left);
                if (node.right != null) tempNodes.add(node.right);

            }
            path++;
            curNodes = tempNodes;
        }
        return path;
    }

当然上面方式做的效率不高:下面快一些.leetcode中是0ms,上面方法用了2ms;

public int getMinDeep(TreeNode treeNode) {
        if (treeNode == null) return 0;
    //初始化一个深度,有节点则为1
        return findMinPath(treeNode, 1);
    }

    int findMinPath(TreeNode node, int deep) {
    //左右都为空,返回当前路径
        if (node.left == null && node.right == null) {
            return deep;
        }
    //左边为空,找到右边最短路径
        if (node.left == null) {
            return findMinPath(node.right, deep + 1);
        }
    //右边为空,找到左边最短路径
        if (node.right == null) {
            return findMinPath(node.left, deep + 1);
        }
    //都不为空,返回左右最短路径
        return Math.min(findMinPath(node.right, deep + 1), findMinPath(node.left, deep + 1));
    }

3.实际遇到的一个问题.

场景: 一个电商系统.我们有各种活动,同时不同活动有不同优惠券.一个活动只能用一张优惠券,一张优惠券也只能用于一个活动.求最优匹配

券A 券B 券C 券D
活动A 3 5 3 5
活动B 1 6 2 4
活动C 6 8 5 4

例如活动A选择了券B;则券B虽然与活动C匹配优惠8,但其不能再被使用;
尝试过用动态规划.但没写出来.感觉是不可行的.最终解决是:在时间复杂度差不多的时候,采用DFS,解决了内存问题.但同时,因为时间复杂度实在是太高.为N!N为行和列中较大数;确实在深度到一定的时候无法计算,只能用贪心算法简单进行计算.
附代码:

public class OptimalCoupon {
    public static long count;
    private double[][] data;
    private int rows;
    private int cols;
    private double maxValue;
    private int[] maxResArray;
    private int[] index;
    boolean[] indexSign;

    public double getMaxValue() {
        return maxValue;
    }

    public OptimalCoupon(double[][] data) {
        // 二维数组,数据源.算法中类型用double
        this.data = data;
        //列数
        this.rows = data.length;
        //行数
        this.cols = data[0].length;
        //最大优惠金额
        this.maxValue = 0;
        //行的坐标数组,数组下标对应列
        this.maxResArray = new int[rows];
        this.index = new int[rows];
        //boolean数组记录已用的列
        this.indexSign = new boolean[cols];
    }

    public int[] getOptimalColumn() {
        getRes(0, 0);
        return this.maxResArray;
    }

    public void getRes(int deep, double curRes) {
        //到了最后一层
        if (deep == rows - 1) {
            //循环最后一行
            for (int i = 0; i < cols; i++) {

                //没用过
                if (!indexSign[i]) {
                    count++;
                    curRes += data[deep][i];
                    //坐标结果集 有row个数,每个数代表每row的clo index
                    // deep = actCoupons.length - 1 也就是 row - 1
                    if (curRes > maxValue) {
                        maxValue = curRes;
                        index[deep] = i;
                        copyToRes(index, maxResArray);

                    }
                    curRes -= data[deep][i];
                }
            }
        } else {
            // 不是最后一层,取上能取到的最小的index,然后继续往下一层
            for (int i = 0; i < cols; i++) {

                //假如没有使用这个index
                if (!indexSign[i]) {
                    count++;
                    //使用
                    indexSign[i] = true;
                    index[deep] = i;
                    //curRes + actCoupons[deep][i] 当前取值
                    getRes(deep + 1, curRes + data[deep][i]);
                    //下一层使用后,恢复
                    indexSign[i] = false;
                }
            }
        }
    }


    void copyToRes(int[] curRes, int[] res) {
        for (int i = 0, len = curRes.length; i < len; i++) {
            res[i] = curRes[i];
        }
    }
}

相关文章

  • 用Python实现树的BFS与DFS

    一、BFS与DFS简介 在理解动态规划、BFS和DFS一文中,已经集合具体例子,介绍了图的BFS与DFS。但是比较...

  • Binary Tree(2)

    BFS vs DFS for Binary Tree What are BFS and DFS for Binar...

  • DFS与BFS LeetCode 刷题小结(一)

    本节我们将汇总一些 LeetCode bfs与dfs相关的题。 关于深度优先搜索(DFS)和广度优先搜索(BFS)...

  • LeetCode 第104题:二叉树的最大深度

    1、前言 2、思路 采用 DFS 或者 BFS 都可以。 3、代码 DFS: BFS:

  • 133. Clone Graph 复制无向图

    bfs dfs

  • BFS和DFS

    DFS BFS

  • BFS与DFS

    广度优先遍历 (BFS) 类似树的层次遍历,首先访问起始顶点v,然后选取与v邻接的全部顶点w1,w2,…wn,进行...

  • DFS与BFS

    以先序遍历打印链表为例: 以中序遍历打印链表为例: 以后序遍历打印链表为例: 以层序遍历打印链表为例:

  • BFS与DFS

    1.什么是BFS,DFS BFS宽度优先搜索.一层一层搜索.把每行的结果存入到队列中,然后遍历求下一层.DFS深度...

  • 树的DFS与BFS

    Data DFS BFS

网友评论

      本文标题:BFS与DFS

      本文链接:https://www.haomeiwen.com/subject/dtrgbctx.html