ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022-005ARTS

2022-02-27 19:06:23  阅读:168  来源: 互联网

标签:Node int graph 005ARTS 2022 new nodes public


ARTS:Algorithm、Review、Tip、Share

  • Algorithm 算法题
  • Review 英文文章
  • Tip 回想一下本周工作中学到的一个小技巧
  • Share思考一个技术观点、社会热点、一个产品或是一个困惑

Algorithm

本周学习图相关的算法,其实算法并不是很复杂,只是图这种数据结构表示起来比较复杂,题目给出的图的表达也并不统一,比如有时碰到邻接表,有时碰到邻接矩阵的表达方式。其实,我们不必在每种表达方式上去练所有的题目,只要掌握了在一种图的表达方式下,练习完相关的算法,碰到其他表达形式,直接转换成这种熟悉的方式,再去处理、解决就好。

一种通用、好用的图结构的表达方式(多个类文件放在一起了):用类 Graph、Node、Edge 分别表示表示图整体结构、图中的节点、图中的边。

public class Graph {
    public Map<Integer, Node> nodes;
    public Set<Edge> edges;

    public Graph() {
        this.nodes = new HashMap<>();
        this.edges = new HashSet<>();
    }
}

public class Node {

    public int value;
    // 入度
    public int in;
    // 出度
    public int out;
    // 与当前节点相邻的节点
    public ArrayList<Node> nexts;
    // 从当前节点出去的边
    public ArrayList<Edge> edges;

    public Node(int value) {
        this.value = value;
        this.in = 0;
        this.out = 0;
        this.nexts = new ArrayList<>();
        this.edges = new ArrayList<>();
    }
}

public class Edge {
    public int weight;
    public Node from;
    public Node to;

    public Edge(int weight, Node from, Node to) {
        this.weight = weight;
        this.from = from;
        this.to = to;
    }
}

先看一道比较简单的图相关的题目

997. 找到小镇的法官

小镇里有 n 个人,按从 1 到 n 的顺序编号。传言称,这些人中有一个暗地里是小镇法官。

如果小镇法官真的存在,那么:

  1. 小镇法官不会信任任何人。
  2. 每个人(除了小镇法官)都信任这位小镇法官。
  3. 只有一个人同时满足属性 1 和属性 2 。

给你一个数组 trust,其中 trust[i] = [ai, bi] 表示编号为 ai 的人信任编号为 bi 的人。

如果小镇法官存在并且可以确定他的身份,请返回该法官的编号;否则,返回 -1 。

示例 1:

输入:n = 2, trust = [[1,2]]
输出:2

示例 2:

输入:n = 3, trust = [[1,3],[2,3]]
输出:3

示例 3:

输入:n = 3, trust = [[1,3],[2,3],[3,1]]
输出:-1

提示:

  • 1 <= n <= 1000
  • 0 <= trust.length <= 104
  • trust[i].length == 2
  • trust 中的所有trust[i] = [ai, bi] 互不相同
  • ai != bi
  • 1 <= ai, bi <= n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-town-judge

解法描述

同题目思考得知:若给定数组中存在法官,则只能存在一人,且如果把给定数组trust看作一个图结构,元素之间的新人关系看作图中的边。则小镇法官对应的节点,其入度为 n-1、出度为 0 ,根据这个条件,就可以判定是否存在小镇法官。

注:因为此题比较简单,并没有使用上面我们定义的图表示方法。

编码实现

public int findJudge(int n, int[][] trust) {
	// 定义两个数组,分别表示对应的数组下标图中节点的入度、出度,遍历数组统计入度出度值。
    int[] in = new int[n + 1];
    int[] out = new int[n + 1];
    for (int[] edge : trust) {
        int from = edge[0];
        int to = edge[1];
        in[to] = in[to] + 1;
        out[from] = out[from] + 1;
    }

    for (int i = 1; i <= n; i++) {
        if (in[i] == n-1 && out[i] == 0) {
            return i;
        }
    }
    return -1;
}

210. 课程表 II(同:207. 课程表)

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。
例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。

示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:[0,1]
解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。

示例 2:

输入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出:[0,2,1,3]
解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2
都应该排在课程 0 之后。 因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。

示例 3:
输入:numCourses = 1, prerequisites = []
输出:[0]

提示: 1 <= numCourses <= 2000 0 <= prerequisites.length <= numCourses *
(numCourses - 1) prerequisites[i].length == 2 0 <= ai, bi < numCourses
ai != bi 所有[ai, bi] 互不相同

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/course-schedule-ii

解法描述

该题目实际是考察的对图的拓扑排序:首先收集入度为 0 的节点,然后去掉以该节点出发的边,再收集另外入度为 0 的节点,以此类推,遍历整个图结构,常用于项目之间有依赖关系的管理。

下面的代码实现中,先将给定的数组方式表示的图结构转换为我们熟悉的表示方法,然后再依次处理入度为 0 的节点。

编码实现

class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {

        Graph graph = this.createGraph(prerequisites, numCourses);
        Queue<Node> zeroQueue = new LinkedList<>();

        for (Node node : graph.nodes.values()) {
            if (node.in == 0) {
                zeroQueue.offer(node);
            }
        }

        List<Integer> topologySortList = new ArrayList<>();
        while (!zeroQueue.isEmpty()) {
            Node poll = zeroQueue.poll();
            topologySortList.add(poll.value);

            for (Edge edge : poll.edges) {
                poll.out--;
                edge.to.in--;
                if (edge.to.in == 0) {
                    zeroQueue.offer(edge.to);
                }
            }
        }
        return topologySortList.size() == numCourses ? topologySortList.stream().mapToInt(Integer::intValue).toArray() : new int[]{};
    }

    public Graph createGraph(int[][] matrix, int numCourses) {
        Graph graph = new Graph();
        for (int i = 0; i < matrix.length; i++) {
            // 拿到每一条边, matrix[i]
            int from = matrix[i][1];
            int to = matrix[i][0];
            if (!graph.nodes.containsKey(from)) {
                graph.nodes.put(from, new Node(from));
            }
            if (!graph.nodes.containsKey(to)) {
                graph.nodes.put(to, new Node(to));
            }
            Node fromNode = graph.nodes.get(from);
            Node toNode = graph.nodes.get(to);
            Edge newEdge = new Edge(fromNode, toNode);
            fromNode.nexts.add(toNode);
            fromNode.out++;
            toNode.in++;
            fromNode.edges.add(newEdge);
            graph.edges.add(newEdge);
        }
        for (int i = 0; i < numCourses; i++) {
            if (!graph.nodes.containsKey(i)) {
                graph.nodes.put(i, new Node(i));
            }
        }
        return graph;
    }
}



class Graph {
    public Map<Integer, Node> nodes;
    public Set<Edge> edges;

    public Graph() {
        this.nodes = new HashMap<>();
        this.edges = new HashSet<>();
    }


}

class Edge {
    public Node from;
    public Node to;

    public Edge(Node from, Node to) {
        this.from = from;
        this.to = to;
    }
}

class Node {

    public int value;
    public int in;
    public int out;
    public ArrayList<Node> nexts;
    public ArrayList<Edge> edges;

    public Node(int value) {
        this.value = value;
        this.in = 0;
        this.out = 0;
        this.nexts = new ArrayList<>();
        this.edges = new ArrayList<>();
    }
}

Review

CollectionHelpersExplained :Guava提供的对于扩展集合框架方面的工作类的介绍

Tip

入职新公司 4 个月以来,对部门相关的业务、项目、开发流程、规范等逐渐熟悉,相信每个公司都有很多内部的规范文档,同样,我这次入职以来也看了很多目前公司的文档,但对于整体的开发流程、规范整理的日常工作类的文档却没有发现,对新入职的及其不友好、找文档也不方便。因此最近花了点时间,整理出目前工作中主要的开发流程、并链接相关联的规范文档,算作一份 日常工作手册。

趁此也发散了一下,其实对于工作中的很多情况,是需要我们即时去做好记录、做好总结的,因为人的大脑着实是“靠不住”的,它更像电脑运行的内存,而不是存储,我们可以用它来处理各种事务,但用它来记住一些事情却会频频出错。

Share

  • 本周内,部门领导给我们做了一次晋升辅导相关的分享,公司对于晋升是有相关的统一标准要求的,但晋升是否成功,对于述职时的演讲也是很重要的,大部分人做的工作,还是需要很好的表达出来才能得到认可的。如何做好晋升演讲,其核心是怎样更好的展示自己、展示自己理解认知的深度、展示自己独特的价值(换做别人不行的)、给公司带来的收益等。
  • 部门内每个月会组织事故复盘会,总结当月遇到的各种大大小小的事故,不限于自己部门的,我认为这种方式真的很不错,从各种遇到的问题中吸取经验教训,不至于用自己撞的头破血流的经验来提高。

标签:Node,int,graph,005ARTS,2022,new,nodes,public
来源: https://blog.csdn.net/lyg673770712/article/details/123167698

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有