这周的作业可谓是一波三折,但是收获了不少,熟悉了广度优先搜索还有符号图的建立。此外还知道了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) {
}
}

coursera 算法二 week 1 wordnet的更多相关文章

  1. Coursera 算法二 week2 Seam Carving

    这周作业设计到的算法是有向无环图的最短路径算法,只需要按照顶点的拓扑顺序去放松顶点即可.而在这个题目中拓扑顺序就是按照行的顺序或列的顺序. 用到的数据结构为一个二维数组picture同来存储每个像素的 ...

  2. Coursera 算法二 week 5 BurrowsWheeler

    本打算周末完成这次作业,但没想到遇到了hard deadline,刚开始看不懂题意,后来发现算法4书上有个类似的问题,才理解了题意.最后晚上加班,上课加班,还好在11:35也就是课程结束前25分钟完成 ...

  3. Coursera 算法二 week 3 Baseball Elimination

    这周的作业不需要自己写算法,只需要调用库函数就行,但是有些难以理解,因此用了不少时间. import edu.princeton.cs.algs4.FlowEdge; import edu.princ ...

  4. Coursera 算法二 week 4 Boggle

    这次的作业主要用到了单词查找树和深度优先搜索. 1.在深度优先搜索中,在当前层的递归调用前,将marked数组标记为true.当递归调用返回到当前层时,应将marked数组标记为false.这样既可以 ...

  5. TensorFlow 入门之手写识别(MNIST) softmax算法 二

    TensorFlow 入门之手写识别(MNIST) softmax算法 二 MNIST Fly softmax回归 softmax回归算法 TensorFlow实现softmax softmax回归算 ...

  6. 分布式共识算法 (二) Paxos算法

    系列目录 分布式共识算法 (一) 背景 分布式共识算法 (二) Paxos算法 分布式共识算法 (三) Raft算法 分布式共识算法 (四) BTF算法 一.背景 1.1 命名 Paxos,最早是Le ...

  7. Floyd算法(二)之 C++详解

    本章是弗洛伊德算法的C++实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3. 弗洛伊德算法的代码说明 4. 弗洛伊德算法的源码 转载请注明出处:http://www.cnblogs.c ...

  8. Dijkstra算法(二)之 C++详解

    本章是迪杰斯特拉算法的C++实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法图解 3. 迪杰斯特拉算法的代码说明 4. 迪杰斯特拉算法的源码 转载请注明出处:http://www.cnbl ...

  9. Prim算法(二)之 C++详解

    本章是普里姆算法的C++实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/sk ...

随机推荐

  1. JSONCPP学习笔记

    基本使用 使用jsoncpp库解析.修改.打印JSON串 源文件 $ cat main.cpp #include <iostream> #include "json/json.h ...

  2. 《OD学hadoop》20160904某旅游网项目实战

    一.ETL操作 抽取数据 日志格式: 分割符号:^A IP地址 服务器时间 二.Java工程 1. 创建项目 copy代码及配置文件 2. 改配置 core-site.xml hbase-site.x ...

  3. 强联通分量之kosaraju算法

    首先定义:强联通分量是有向图G=(V, E)的最大结点集合,满足该集合中的任意一对结点v和u,路径vu和uv同时存在. kosaraju算法用来寻找强联通分量.对于图G,它首先随便找个结点dfs,求出 ...

  4. iPhone摄影中的深度捕捉(WWDC2017-Session 507)

    507是深度媒体相关的概念层面的内容.主要为下面4个部分: Depth and disparity on iPhone 7 Plus Streaming depth data from the cam ...

  5. [转]黑幕背后的__block修饰符

    http://www.cocoachina.com/ios/20150106/10850.html 我们知道在Block使用中,Block内部能够读取外部局部变量的值.但我们需要改变这个变量的值时,我 ...

  6. MarkDown折叠语法

    1.语法代码 程序员的本质 程序的进阶和优化 1.简化人的操作,更少的代码做更多的事情 2.节省时间效率,在更短的时间内做更多的事情 3.占用内存,占更少的内存做更多的事情 <details&g ...

  7. Unity 行为树-节点间数据传递

    一.引言 有以下小场景: 节点A:发现了 敌人. 节点B:追逐敌人. 对于同一个敌人物体,节点AB之间是如何传递数据 的呢? 二.数据传递的3种方式 1.共享变量:面板中创建局部或者全局的共享变量Te ...

  8. 1101 Quick Sort(25 分

    There is a classical process named partition in the famous quick sort algorithm. In this process we ...

  9. spring boot test MockBean

    使用spring boot , MockBean @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) p ...

  10. C# Task任务详解及其使用方式

    https://blog.csdn.net/younghaiqing/article/details/81455410 C#多线程编程笔记(4.3)-Task任务中实现取消选项 https://blo ...