• coursera 算法二 week 1 wordnet


    这周的作业可谓是一波三折,但是收获了不少,熟悉了广度优先搜索还有符号图的建立。此外还知道了Integer.MAX_VALUE。

    SAP:

    求v和w的大概思路是对v和w分别广度优先搜索,然后遍历图中每一个顶点,如果v和w都可以到达一个顶点,就计算v和w到这一顶点的距离和,最后求出最短的距离以及对应的顶点便是所求length和ancestor。

    至于Iterable<Integer> v和Iterable<Integer> w,开始我是求v中每一个顶点和w中的每一个顶点的距离,然后求出最短距离,但提交后时间测试通不过。参考了其他人的一些博客后发现可以遍历一次完成对v或w的广度优先搜索,于是自己写了一个BFS类。然而这次提交出现了OperationCountLimitExceededException,最后检查了半天才发现bfs时丢了一句   ' if(!marked[w]) '。。。后来发现官方提供的BreadthFirstDirectedPaths类可以完成Iterable<Integer> v的广度优先搜索,于是干脆直接调用这个。

    但是提交后还是有问题。。。对于没有共同祖先的情况判断不正确,不能返回-1,检查了半天发现每次求length或ancestor都应该在前面加上 anc = -1; 否则这次求返回的是上次的anc。

    import edu.princeton.cs.algs4.*;
    import edu.princeton.cs.algs4.In;
    
    public class SAP {
        private Digraph G;
        private int anc = -1;
       // constructor takes a digraph (not necessarily a DAG)
       public SAP(Digraph G) {
           if(G == null) throw new IllegalArgumentException();
           this.G = new Digraph(G);
       }
    
       // length of shortest ancestral path between v and w; -1 if no such path
       public int length(int v, int w) {
           if(v < 0 || v > G.V() - 1 || w < 0 || w > G.V() - 1)
               throw new IllegalArgumentException();
           anc = -1;
           
           BreadthFirstDirectedPaths bv = new BreadthFirstDirectedPaths(G, v);
           BreadthFirstDirectedPaths bw = new BreadthFirstDirectedPaths(G, w);
           
           int minLength = Integer.MAX_VALUE;
           
           for(int i = 0; i < G.V(); i++) {
               if(bv.hasPathTo(i) && bw.hasPathTo(i)) {
                   int l = bv.distTo(i) + bw.distTo(i);
                   if(l < minLength) {
                       minLength = l;
                       anc = i;
                   }
               }
           }
           
           if(minLength == Integer.MAX_VALUE) return -1;
           else return minLength;
          
       }
    
       // a common ancestor of v and w that participates in a shortest ancestral path; -1 if no such path
       public int ancestor(int v, int w) {
           length(v, w);
           return anc;
       }
        
       // length of shortest ancestral path between any vertex in v and any vertex in w; -1 if no such path
       public int length(Iterable<Integer> v, Iterable<Integer> w) {
           if(v == null || w == null)
               throw new IllegalArgumentException();
           anc = -1;
           
           for(int i : v) {
               if(i < 0 || i > G.V() - 1)
                    throw new IllegalArgumentException();
           }
           for(int i : w) {
               if(i < 0 || i > G.V() - 1)
                    throw new IllegalArgumentException();
           }
           
           BreadthFirstDirectedPaths bv = new BreadthFirstDirectedPaths(G, v);
           BreadthFirstDirectedPaths bw = new BreadthFirstDirectedPaths(G, w);
           
           int minLength = Integer.MAX_VALUE;
           
           for(int i = 0; i < G.V(); i++) {
               if(bv.hasPathTo(i) && bw.hasPathTo(i)) {
                   int l = bv.distTo(i) + bw.distTo(i);
                   if(l < minLength) {
                       minLength = l;
                       anc = i;
                   }
               }
           }
           
           if(minLength == Integer.MAX_VALUE) return -1;
           else return minLength;
       }
    
       // a common ancestor that participates in shortest ancestral path; -1 if no such path
       public int ancestor(Iterable<Integer> v, Iterable<Integer> w) {
           length(v, w);
           return anc;
       }
    
       // do unit testing of this class
       public static void main(String[] args) {
            
        }
    }

    WordNet:

    wordnet涉及到符号图的问题,开始用ST<String, Integer>来完成noun到id的索引,后来发现一个noun可能对应多个id,于是改为ST<String, Bag<Integer>>。

    需要检查有向图是否合格:1.不能有环。通过类DirectedCycle完成。 2.只能有一个root。经参考别人的博客发现一个很巧妙的方法,如果一个顶点是根,那么它不指向其它顶点,所以它不会出现在hypernyms每行的第一个id。

    方法sap需要通过id得到noun,用数组的话不能提前知道数组大小,于是参考网上用ArrayList<String>完成id到noun的索引。

    import edu.princeton.cs.algs4.*;
    import java.util.ArrayList;
    
    public class WordNet {
        private ST<String, Bag<Integer>> st;
        private ArrayList<String> idList;
        private Digraph G;
        
       // constructor takes the name of the two input files
       public WordNet(String synsets, String hypernyms) {
           if(synsets == null || hypernyms == null) throw new IllegalArgumentException();
           
           st = new ST<String, Bag<Integer>>();
           idList = new ArrayList<String>();
           
           int count = 0;
           In in1 = new In(synsets);
           while(in1.hasNextLine()) {
               String[] a = in1.readLine().split(",");
               String[] a2 = a[1].split(" ");
               
               for(int i = 0; i < a2.length; i++) {
                   if(st.contains(a2[i])) st.get(a2[i]).add(Integer.parseInt(a[0]));
                   else {
                        Bag<Integer> b = new Bag<Integer>();
                        b.add(Integer.parseInt(a[0]));
                        st.put(a2[i], b);
                   }
               }
               count++;
               idList.add(a[1]);
           }
           
           G = new Digraph(count);
           In in2 = new In(hypernyms);
           boolean[] isNotRoot = new boolean[count];
           int rootNumber = 0;
           
           while(in2.hasNextLine()) {
               String[] a = in2.readLine().split(",");
               isNotRoot[Integer.parseInt(a[0])] = true;
               for(int i = 1; i < a.length; i++)
                   G.addEdge(Integer.parseInt(a[0]), Integer.parseInt(a[i]));
           }
           
           for(int i = 0; i < count; i++) {
               if(!isNotRoot[i]) rootNumber++;
           }
           DirectedCycle d = new DirectedCycle(G);
           if(rootNumber > 1 || d.hasCycle()) throw new IllegalArgumentException();
       }
       
       // returns all WordNet nouns
       public Iterable<String> nouns() {
           return st.keys();
       }
    
       // is the word a WordNet noun?
       public boolean isNoun(String word) {
           if(word == null) throw new IllegalArgumentException();
           return st.contains(word);
       }
    
       // distance between nounA and nounB (defined below)
       public int distance(String nounA, String nounB) {
           if(nounA == null || nounB == null || !isNoun(nounA) || !isNoun(nounB))
               throw new IllegalArgumentException();
            SAP s = new SAP(G);
            Bag<Integer> ida = st.get(nounA);
            Bag<Integer> idb = st.get(nounB);
            
            return s.length(ida, idb);
       }
    
       // a synset (second field of synsets.txt) that is the common ancestor of nounA and nounB
       // in a shortest ancestral path (defined below)
       public String sap(String nounA, String nounB) {
           if(nounA == null || nounB == null || !isNoun(nounA) || !isNoun(nounB))
               throw new IllegalArgumentException();
            SAP s = new SAP(G);
            Bag<Integer> ida = st.get(nounA);
            Bag<Integer> idb = st.get(nounB);
            
            int root = s.ancestor(ida, idb);
            return idList.get(root);
       }
        
       // do unit testing of this class
       public static void main(String[] args) {
          
    
       }
    }

    Outcast:

    public class Outcast {
        private WordNet wordnet;
        
        // constructor takes a WordNet object
        public Outcast(WordNet wordnet) {
            this.wordnet = wordnet;
        }
        // given an array of WordNet nouns, return an outcast   
        public String outcast(String[] nouns) {
            int length = nouns.length;
            int[][] distance = new int[length][length];
            
            for(int i = 0; i < length; i++) {
                for(int j = i; j < length; j++) {
                    distance[i][j] = wordnet.distance(nouns[i], nouns[j]);
                }
            }
            
            int maxDistance = 0;
            int sum = 0;
            int num = 0;
            for(int i = 0; i < nouns.length; i++) {
                sum = 0;
                for(int j = 0; j < nouns.length; j++) {
                    if(i < j)
                        sum += distance[i][j];
                    else
                        sum += distance[j][i];
                }
                
                if(sum > maxDistance) {
                    maxDistance = sum;
                    num = i;
                }
            }
            
            return nouns[num];
        }
        // see test client below
        public static void main(String[] args) {
        }        
    }
    View Code
  • 相关阅读:
    输入框只能输入正数且保留小数后2位数字,正则
    vscode安装ESlint配置
    kubreretes && docker 模块
    python3安装sqlite3库
    dokcerfile 制作Msql镜像
    前端模板
    Python SMTP发送邮件
    k8s-api
    openpyxl
    k8s mysql主从
  • 原文地址:https://www.cnblogs.com/lxc1910/p/8051822.html
Copyright © 2020-2023  润新知