一個網站域名,如"discuss.leetcode.com",包含了多個子域名。做爲頂級域名,經常使用的有"com",下一級則有"leetcode.com",最低的一級爲"discuss.leetcode.com"。當咱們訪問域名"discuss.leetcode.com"時,也同時訪問了其父域名"leetcode.com"以及頂級域名 "com"。 給定一個帶訪問次數和域名的組合,要求分別計算每一個域名被訪問的次數。其格式爲訪問次數+空格+地址,例如:"9001 discuss.leetcode.com"。java
["9001 discuss.leetcode.com"]算法
["9001 discuss.leetcode.com", "9001 leetcode.com", "9001 com"]數組
例子中僅包含一個網站域名:"discuss.leetcode.com"。按照前文假設,子域名"leetcode.com"和"com"都會被訪問,因此它們都被訪問了9001次。app
這道題目相對來講仍是比較簡單的,看到這種String
、這種格式,平頭哥首先想到的是String
的substring()
、split()
兩個方法將string
轉成數組或者新的字符串,事實證實平頭哥的想法還闊以,竟然居於這兩個方法實現了子域名訪問統計,真是瞎貓碰上死耗子。可是平頭哥是一名具備專研精神的非專業搬磚員,通過平頭哥不嚴格的測試得出,subString()
方法比split()
方法效率高出一大截。這種不知道有多少層的東西用遞歸或者循環總歸是不會錯的,爲何這麼說呢?由於以平頭哥的智商也想不出其餘方式啦。平頭哥基於遞歸或者循環實現了三種解決方式,那平頭哥就來給小夥伴們介紹介紹這三種方式。dom
/** * for +while 方法 * @param cpdomains * @return */
public static List<String> whileSolution(String[] cpdomains){
// 用來存返回結果
List<String> list = new ArrayList<String>();
// 用來計數統計
Map<String, Integer> map = new HashMap<>();
for (String cpdomain : cpdomains) {
// // 先截取訪問數和域名
// String[] temp = cpdomain.split(" ");
// // 訪問數
// int viewCount = Integer.valueOf(temp[0]);
// // 域名
// String domain = temp[1];
int indexOf = cpdomain.indexOf(" ");
// 訪問數
int viewCount = Integer.valueOf(cpdomain.substring(0, indexOf));
// 域名
String domain = cpdomain.substring(indexOf + 1);
while (domain.indexOf(".") !=-1){
mapPutOrAdd(map,domain,viewCount);
domain = domain.substring(domain.indexOf(".")+1);
}
// 最後一個頂級域名
mapPutOrAdd(map,domain,viewCount);
}
for (String key :map.keySet())
list.add(map.get(key)+" "+key);
return list;
}
複製代碼
利用 while
循環來判斷域名中是否包含.
,若是包含.
,則說明只要有一個子域名,由於indexOf()
方法是從左往右查找的,只要找到就返回.
所在字符串的位置,沒有找到就返回-1
。若是找到了,就利用substring()
方法從返回位置的後一位開始截取到字符串的最後一位,做爲新的字符串,繼續走上面的流程,知道循環結束。學習
/** * 三層for 循環 * @param cpdomains * @return */
public static List<String> forSolution(String[] cpdomains) {
List<String> list = new ArrayList<String>();
Map<String, Integer> map = new HashMap<>();
// 遍歷數組
for (String cpdomain : cpdomains) {
// // 先截取訪問數和域名
// String[] temp = cpdomain.split(" ");
// // 訪問數
// int viewCount = Integer.valueOf(temp[0]);
// // 域名
// String domain = temp[1];
int indexOf = cpdomain.indexOf(" ");
// 訪問數
int viewCount = Integer.valueOf(cpdomain.substring(0, indexOf));
// 域名
String domain = cpdomain.substring(indexOf + 1);
String[] domains = domain.split("\\.");
if (domains.length == 0) continue;
// 拼接出多級域名,都塞入map
for (int i = 0; i < domains.length; i++) {
StringBuilder key = new StringBuilder(domains[i]);
for (int j = i + 1; j < domains.length; j++) {
key.append('.');
key.append(domains[j]);
}
mapPutOrAdd(map,key.toString(), viewCount);
}
}
for (String key :map.keySet())
list.add(map.get(key)+" "+key);
return list;
}
複製代碼
for
循環的實現是平頭哥帶來的三種實現中,效率最低的。因此小夥伴們能不用雙層for
就堅定不用。for
循環最要利用split()
方法將域名分離出現,例如discuss.leetcode.com
分紅discuss
、leetcode
、com
。而後雙層遍歷將域名組合起來,最外層第一次遍歷完以後獲得discuss.leetcode.com
,第二次遍歷完以後獲得leetcode.com
,第三次遍歷完以後獲得com
。這樣最後也獲得了每一個域名的訪問次數。測試
public static List<String> recurveSolution(String[] cpdomains){
List<String> list = new ArrayList<String>();
Map<String, Integer> map = new HashMap<>();
// 遍歷數組
for (String cpdomain : cpdomains) {
// 先截取訪問數和域名
String[] temp = cpdomain.split(" ");
// 訪問數
int viewCount = Integer.valueOf(temp[0]);
// 域名
String domain = temp[1];
// 遞歸方法
recurve(map,domain,viewCount);
}
for (String key :map.keySet())
list.add(map.get(key)+" "+key);
return list;
}
/** * 遞歸方法 * @param map map集合 * @param domain 網站域名 * @param viewCount 訪問數 * @return */
public static Map<String,Integer> recurve(Map<String,Integer> map,String domain,Integer viewCount){
if (domain.indexOf(".") != -1){
mapPutOrAdd(map,domain,viewCount);
return recurve(map, domain.substring(domain.indexOf(".")+1),viewCount);
}else {
mapPutOrAdd(map,domain,viewCount);
return map;
}
}
private static void mapPutOrAdd(Map<String,Integer> map, String key, Integer val) {
if (map.containsKey(key)) {
map.put(key,map.get(key) + val);
} else {
map.put(key,val);
}
}
複製代碼
遞歸方法跟while
方式差很少,效率也不相上下。由於咱們不知道域名有多少層,用遞歸來作是很是合適的,由於遞歸就是爲這個而生。每次遞歸的時候咱們現將域名添加到map
中,跟while
同樣咱們也用indexOf(".")
來判斷域名中是否含有子域名,若是存在,則截取新的域名繼續調用自身,直到沒有子域名爲止。網站
以上就是平頭哥給小夥伴們帶來關於子域名訪問計數的算法分享,不知道是否給小夥伴們講明白?對於這道算法題,小夥伴們你是否還有其餘思路呢?請在留言區與其餘的小夥伴分享吧。ui