leetcode雕虫小技mediu 684. Redundant Connection

题干: https://leetcode.com/problems/redundant-connection/

 

这题地思路不难,就是在边中找环,取环中所有边中index最大者即可。

 

问题是怎么找环呢?我的大体思路是从任意一个顶点开始尝试,使用回溯法,只要发现环路,立即停止并输出该环

说是这么说,具体怎么做呢?亲自试了下写起来并没有那么容易。

首先得收集一个数据结构,每个顶点对应哪些边,用一个Map来表示。

然后对每条边进行尝试时,需要做一些判断,该边是否有访问过,没 访问过则加入选边列表,递归进行,每次递归都要首先判断,目前已选的边是否已经构成环路,若是,则进行输出赋值。还要注意每次选完边后,你得知道当前最后跑到的节点是谁,否则你不知道洗一次选择从哪里分叉,所以需要写个小的辅助函数来根据已选边确定最后节点,方法是最后边的两个节点减去倒数第二条边的两个节点即可(差集)。

代码如下:

public int[] findRedundantConnection(int[][] edges) {
        // collect edges to map of int->list of edge index
        Map<Integer, List<Integer>> vertexEdgeIndexMap = new HashMap<>();
        for(int i=0;i<edges.length;i++){
            add2map(vertexEdgeIndexMap, edges[i][0], i);
            add2map(vertexEdgeIndexMap, edges[i][1], i);
        }

        for(Integer vertex: vertexEdgeIndexMap.keySet()){
            // if vertex in circle, return the max index edge in the circle, else return -1
            int code = checkVertexInCircle(vertex, vertexEdgeIndexMap, edges);
            if(code==-1){
                continue;
            }else{
                return edges[code];
            }
        }

        // this should never happen, because we can guarantee the input contains loop
        return new int[0];
    }

    private int checkVertexInCircle(int vertex, Map<Integer, List<Integer>> vertexEdgeIndexMap, int[][] edges){
        List<Integer> edgeChoices = new ArrayList<>();
        List<Integer> circleEdges = new ArrayList<>();

        traverse(vertex, vertexEdgeIndexMap, edges, edgeChoices, circleEdges);

        //可能本顶点有环,也可能无环
        if(circleEdges.size()>0){
            return circleEdges.stream().max(Integer::compare).get();
        }else{
            return -1;
        }
    }


    // 假设arr1长度为2
    private int exclude(int[] arr1, int[] arr2){
        List<Integer> tt = Arrays.stream(arr2).boxed().collect(Collectors.toList());
        return tt.contains(arr1[0])?arr1[1]:arr1[0];
    }

    private boolean isCircle(List<Integer> edgeChoices, int[][] edges){
        int startVertex = exclude(edges[edgeChoices.get(0)], edges[edgeChoices.get(1)]);
        int endVertex = exclude(edges[edgeChoices.get(edgeChoices.size()-1)], edges[edgeChoices.get(edgeChoices.size()-2)]);

        if(startVertex==endVertex){
            return true;
        }
        return false;
    }

    private void traverse(int vertex, Map<Integer, List<Integer>> vertexEdgeIndexMap, int[][] edges,
                          List<Integer> edgeChoices, List<Integer> circleEdges){

        if(edgeChoices.size()>=3){
            // if edgeChoices forms a circle, set circleEdges once for all and return
            if(isCircle(edgeChoices, edges)){
//                circleEdges = new ArrayList<>(edgeChoices);
                circleEdges.clear();
                for(Integer e: edgeChoices){
                    circleEdges.add(e);
                }
                return;
            }
        }

        List<Integer> choices = new ArrayList<>();
        if(edgeChoices.size()<1){
            choices = vertexEdgeIndexMap.get(vertex);
        }else{
            // find the final point x
            int x;
            if(edgeChoices.size()==1){
                x = (edges[edgeChoices.get(0)][0]==vertex?edges[edgeChoices.get(0)][1]:edges[edgeChoices.get(0)][0]);
            }else{
                int[] pointsInLast  = edges[edgeChoices.get(edgeChoices.size()-1)];
                int[] pointsInSecondLast  = edges[edgeChoices.get(edgeChoices.size()-2)];
                x = exclude(pointsInLast, pointsInSecondLast);
            }
            choices = vertexEdgeIndexMap.get(x);
        }
        for(Integer c: choices){
            if(!edgeChoices.contains(c)){
                edgeChoices.add(c);
                traverse(vertex, vertexEdgeIndexMap, edges, edgeChoices, circleEdges);
                edgeChoices.remove(edgeChoices.size()-1);
            }
        }
    }

    private void add2map(Map<Integer, List<Integer>> vertexEdgeIndexMap, Integer key, Integer val){
        if(vertexEdgeIndexMap.get(key)!=null){
            vertexEdgeIndexMap.get(key).add(val);
        }else{
            List<Integer> eIndexs = new ArrayList<>();
            eIndexs.add(val);
            vertexEdgeIndexMap.put(key, eIndexs);
        }
    }

 

反思:这题这题主要在辅助函数上写了一大堆,花了不少时间,应该不是最优雅的写法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值