1、题目描述
2、解题思路
其实本题就是一个简单的层序遍历问题,用 BFS 即可解决,但是题目描述比较晦涩。
题目解读:
1、给定一个 startUrl,这个 startUrl 的页面存在若干个链接,可以用 HtmlParser 接口的 getUrls(String url) 方法获取该页面的所有链接;
2、返回能够访问到的、和 startUrl 具有同样的主机名的所有链接。
本题的 BFS 逻辑中涉及到“查看当前链接是否已使用”的操作,建议使用 HashSet 来临时存储,到需要返回的时候再把 set 的数据装入 list 中,可以提升 10 倍的速度,原因在于 HashSet 的查找速度比 ArrayList 快。
3、解题代码
/**
* // This is the HtmlParser's API interface.
* // You should not implement it, or speculate about its implementation
* interface HtmlParser {
* public List<String> getUrls(String url) {}
* }
*/
import java.util.*;
class Solution {
public List<String> crawl(String startUrl, HtmlParser htmlParser) {
Queue<String> queue = new LinkedList<>();
// 这里用 HashSet 比直接用 ArrayList 快十倍,到最后再装入 list
HashSet<String> set = new HashSet<>();
set.add(startUrl);
queue.add(startUrl);
while (!queue.isEmpty()) {
String currentUrl = queue.poll();
List<String> nextUrls = htmlParser.getUrls(currentUrl);
for (String nextUrl : nextUrls) {
if (!set.contains(nextUrl) && getHostName(nextUrl).equals(getHostName(currentUrl))) {
// 如果链接没使用过且和 currentUrl 同主机,则有效
set.add(nextUrl);
queue.add(nextUrl);
}
}
}
return new ArrayList<>(set);
}
/**
* 获取 url 的主机名
*
* @param url 示例:http://leetcode.com/problems
* @return 示例输出:leetcode.com
*/
private String getHostName(String url) {
url = url.substring(7);
if (url.contains("/")) {
int end = url.indexOf('/'); // 第一次出现斜杠的索引位置
return url.substring(0, end);
} else {
return url;
}
}
}