美文网首页
网易游戏数据挖掘面试算法之水陆矩阵(DFS)

网易游戏数据挖掘面试算法之水陆矩阵(DFS)

作者: sawyer_2172 | 来源:发表于2018-04-10 14:37 被阅读81次

    今天收到网易游戏的拒信, 心里有点失落, 更多是无奈吧, 各种deadline, 实在是没时间准备面试, 而且千里迢迢从香港坐火车到杭州, 也是够受的.

    选择本身就是双向的, 本身对网易暖暖的游戏不太感冒, 也并不想去杭州.

    Anyway, 此处不留爷, 自有留爷处.

    这里记录下面试过程中的算法题: 水陆矩阵.

    描述

    给一个矩阵, 1代表陆地, 0代表海洋, 上下左右移动1步内的元素算是相邻的, 连在一起的1算是一块陆地.

           [{1, 1, 1, 1, 0},
    
           {0, 1, 0, 1, 0},
    
           {0, 1, 1, 0, 1}]
    

    这道题后来查了下是亚马逊的面试题 1, 具体可以通过链接看一下描述.

    分析

    面试时候想法是用DP, 但是其实我自己都没底, 最后大概说了下我的想法, 直观的想通过某个1的上下左右去找, 事实上是DFS的思想(笑), 但具体让我写代码没怎么完整实现, 所以趁着还有点印象, 又思考了下.

    策略是从左上角, 按行优先遍历所有的元素. 如果发现是陆地, 就从这个陆地开始往右和往下迭代(DFS).

    实现

    具体实现有如下几个问题:

    1. Node节点需要保留访问标记(当然也可以外部通过HashSet记录).

    2. 如何在迭代过程中记录访问路径,这里我是通过在参数列表传一个HashSet引用, 如果是当前节点是陆地就自己加进去.

    3. 如何定义陆地集合. 我是用List<HashSet<String>>来记录, HashSet中保存的是陆地的行列号字符串.

    4. 如何匹配一轮DFS查找后返回的HashSet内容. 针对每个元素, 迭代返回的HashSet可能是属于某个land的一部分, 那么需要把它加入到这个land中. 这里只要判断HashSet是否和外部保存的List<HashSet<String>>中每个Set有没有交集.

    代码

    定义数据结构: LandMatrix

    public class LandMatrix {
        public boolean isVisted = false;
        public boolean isLand = false ;
        public LandMatrix(){
        }
        public LandMatrix(boolean isLand){
            this.isLand = isLand ;
        }
        
        @Override
        public String toString() {
            return "isLand:"+isLand+",isVisted:"+isVisted;
        }
    }
    

    算法: LandMatrixAlgorithm

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    public class LandMatrixAlgorithm {
    
        static int MAX_DEPTH = 5;
    
        public static void main(String[] args) {
            List<ArrayList<LandMatrix>> matrix = new ArrayList<ArrayList<LandMatrix>>();
            int sizeOfMatrix = 1000;
            for (int i = 0; i < sizeOfMatrix; i++) {
                ArrayList<LandMatrix> tmpList = new ArrayList<LandMatrix>();
                matrix.add(tmpList);
                for (int k = 0; k < sizeOfMatrix; k++) {
                    LandMatrix l1 = new LandMatrix();
                    tmpList.add(l1);
                }
            }
            // 0-1
            // 0-3
            // 2-0,2-1,2-2,3-1
            // 3-3
            for (int m = 0; m < sizeOfMatrix; m++) {
                matrix.get((int) (Math.random() * sizeOfMatrix)).get((int) (Math.random() * sizeOfMatrix)).isLand = true;
            }
            // matrix.get(0).get(3).isLand = true;
            // matrix.get(2).get(0).isLand = true;
            // matrix.get(2).get(1).isLand = true;
            // matrix.get(2).get(2).isLand = true;
            // matrix.get(3).get(1).isLand = true;
            // matrix.get(3).get(3).isLand = true;
    
            // control the depth of stack
            int depth = 1;
            long start = System.currentTimeMillis();
            List<HashSet<String>> landsSet = new ArrayList<HashSet<String>>();
            for (int i = 0; i < matrix.size(); i++) {
                for (int j = 0; j < matrix.size(); j++) {
                    HashSet<String> landSet = new HashSet<String>();
                    DFS(matrix, i, j, depth, landSet);
                    if (landSet.size() == 0) {
                        continue;
                    }
                    boolean isIn = false;
                    for (int k = 0; k < landsSet.size(); k++) {
                        HashSet<String> testSet = new HashSet<String>();
                        testSet.addAll(landsSet.get(k));
                        testSet.retainAll(landSet);
                        if (testSet.size() != 0) {
                            landsSet.get(k).addAll(landSet);
                            isIn = true;
                        }
                    }
                    if (!isIn || landsSet.size() == 0) {
                        landsSet.add(landSet);
                    }
                }
            }
            System.out.println("Time:" + (System.currentTimeMillis() - start) + "\n" + landsSet);
        }
    
        public static void DFS(List<ArrayList<LandMatrix>> matrix, int i, int j, int depth, HashSet<String> landSet) {
            if (isEnd(matrix, i, j, depth) || matrix.get(i).get(j).isVisted) {
                return;
            }
            matrix.get(i).get(j).isVisted = true;
            if (matrix.get(i).get(j).isLand == false) {
                return;
            } else {
                // add to is lands
                landSet.add(i + "-" + j);
            }
            // RIGHT
            if (canMove(matrix, i + 1, j)) {
                DFS(matrix, i + 1, j, depth + 1, landSet);
            }
            // DOWN
            if (canMove(matrix, i, j + 1)) {
                DFS(matrix, i, j + 1, depth + 1, landSet);
            }
        }
    
        private static boolean canMove(List<ArrayList<LandMatrix>> matrix, int i, int j) {
            if (i < matrix.size() && j < matrix.get(i).size()) {
                return true;
            }
            return false;
        }
    
        private static boolean isEnd(List<ArrayList<LandMatrix>> matrix, int i, int j, int depth) {
            if (depth > LandMatrixAlgorithm.MAX_DEPTH) {
                return true;
            }
            return false;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:网易游戏数据挖掘面试算法之水陆矩阵(DFS)

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