感覺要有一個可以碎碎念的地方,所以就有了這一篇。最近要準備的有點多,所以決定先暫停Leetcode題解,把時間挪給更優先的事情。
網路教學與日常學習
網路教學與日常學習
人生第一次面試
GNS3安裝與設定教學(2.2.10) ※疑難:GNS3無法順利連上VM。(VMware Player)
第一步:下載 GNS3
![]() |
| 下載 GNS3 |
第二步:安裝 GNS3
![]() |
| 一路按「Next」或「I Agree」 |
![]() |
| 如果沒有VM檔的可以勾選,可以先把VM檔下載回來,但一般不用勾。 至於Tools,新手全勾選,有些是必須安裝才能順利使用。 |
| 官方對於Tools的簡短敘述 |
![]() |
| 選一個VM Type的VM檔 (個人建議選 VMware Workstation) |
第三步:設定 GNS3
![]() |
| 首次進入GNS3,會看到這個畫面。 |
![]() |
| 沒有特別需求就按「Next >」 |
![]() |
| 需要先在VM Software匯入VM檔才能下一步 ※CPU數跟記憶體預設為 1、2048MB,VM檔預設也是如此,二者建議相同。 若第一次用就不去改參數,因為用預設下,二者也會一致。 |
如果是新手,而且又用「VMware Workstation Player」的,接下來是
「十分重要」
![]() |
| VM進入「Test」測試,就可以知道VM是否能上網。 |
疑難雜症區
GNS3無法順利連上VM。(VMware Player)
![]() |
| 打開GNS3,GNS3也順利執行VM,但發現VM不通 |
![]() |
| 拖曳 Cloud 跟 VPCS (在 local server) 對 Cloud 按右鍵點 Console |
![]() |
| 勾選「Show special Ethernet interfaces」 然後上方切到「VMware Network Adapter WMnet1」 點「Add」 |
![]() |
| 按下OK後,把 PC1 跟 Cloud 的 VMnet1 接起來。 |
![]() |
| 啟動PC1,然後進入Console |
![]() |
| 這時用「CMD」打「ipconfig」去查「VMnet1」的位置 參考並選一個IP位置要做為PC1的IP位置。 (不知道的可以拿尾碼加1,此例為10.1.1.4) |
![]() |
| 設定IP位置,並 嘗試Ping VMnet1(位置在ipconfig可查) 嘗試Ping VM(寫在VM的資訊頁) |
Leetcode題解 Python & C#六月挑戰DAY20 Permutation Sequence
Python
class Solution:
def getPermutation(self, n: int, k: int) -> str:
result = ""
nums = [str(i) for i in range(1, n+1)]
method = [1]
for i in range(1, n):
method.append(method[i-1]*i)
k -= 1
for i in range(n-1, 0, -1):
result += nums.pop(k // method[i])
k = k % method[i]
result += nums.pop()
return result
C#
public class Solution {
public string GetPermutation(int n, int k) {
var result = new List();
var number = new List();
var factorial = new int[9];
factorial[0] = 1;
for(int i = 1; i < n; i ++)
{
factorial[i] = factorial[i-1]*i;
number.Add(i);
}
number.Add(n);
k -= 1;
for(int i = n-1; i > 0; i--)
{
result.Add(number[k / factorial[i]]);
number.RemoveAt(k / factorial[i]);
k = k % factorial[i];
}
result.Add(number[0]);
return string.Join("", result);
}
}
Leetcode題解 Python:六月挑戰DAY19 Longest Duplicate Substring
Python
class Solution:
def longestDupSubstring(self, S: str) -> str:
hashMap = dict()
count = 0
nums = []
for c in S:
if c not in hashMap:
hashMap[c] = count
count += 1
nums.append(hashMap[c])
mod = 2**64
def search(length):
SubStrHash = 0
for i in range(length):
SubStrHash = (SubStrHash*count + nums[i])%mod
hashset = {SubStrHash}
al = (count**length)%mod
for i in range(length, n):
SubStrHash = (SubStrHash*count - nums[i-length]*al + nums[i])%mod
if SubStrHash in hashset:
return i
hashset.add(SubStrHash)
return -1
n = len(S)
l, r = 0, n
end = -1
while r > l:
m = (r - l)//2 + l
res = search(m+1)
if res == -1:
r = m
else:
l = m + 1
end = res
return "" if end == -1 else S[end - r + 1: end+1]
Leetcode題解 Python & C#:六月挑戰DAY18 H-Index II
Python
class Solution:
def hIndex(self, citations: List[int]) -> int:
if not citations: return 0
n = len(citations)
l, r = 0, n
while l < r:
m = (r-l)//2 + l
if citations[m] >= n-m:
r = m
else:
l = m + 1
return n-r
C#
public class Solution {
public int HIndex(int[] citations) {
int l = 0;
int r = citations.Length;
while(l < r)
{
int m = (r-l)/2 + l;
if(citations[m] >= citations.Length - m)
r = m;
else
l = m + 1;
}
return citations.Length - r;
}
}
testcase
[100]
[]
[1]
[0,1,3,5,6]
[0,1,2,5,6]
Wildcard Mask 用Python計算去簡化輸入
Repl.it (線上執行Python) ※支援手機(Android IOS)OneWildcardMask: 將輸入的IP位置用一組Network和WildcardMask表示。MultiWildcardMask: 用一或多組Network和WildcardMask去表示所有輸入的IP的。
"""
ips間互相做XOR得到結果一
再把結果一做OR,得到單一最低限度的wildcard mask
"""
ips = [[192,168,0,7], [192,168,0,15]]
result = [set(), set(), set(), set()]
wc = []
# 兩兩 XOR => 計算結果1
for i1 in range(len(ips)-1):
for i2 in range(i1+1, len(ips)):
for i3 in range(4):
result[i3].add(ips[i1][i3] ^ ips[i2][i3])
# 計算結果1 做 OR 總計算
for i in range(4):
num = 0
for res in result[i]:
num |= res
wc.append(num)
print(wc)
"""
再次簡化
"""
ips = [[192,168,0,7], [192,168,0,15]]
wc = [0, 0, 0, 0]
for i1 in range(len(ips)-1):
for i2 in range(i1+1, len(ips)):
for i3 in range(4):
wc[i3] |= (ips[i1][i3] ^ ips[i2][i3])
print(wc)雖然算得出來,但是因為一開始要算兩兩成對XOR,所以會至少要算 n(n-1)/2 次,如果要把一個範圍納入,如最後二位可[0, 255]間,會計算(255*255)*((255*255)-1)/1次。那會運算相當久,但對人來說,那可能是一秒就能算完的。換個想法,既然在IP位置清單內的都要能符合,不如從一個 (Network, Wildcard) 的組合,對應每一個IP位置去做一些修改,讓每一個都能符合條件。
ips = []
for l1 in range(256):
for l2 in range(256):
ips.append([192, 168, l1, l2])
wc = [[[0,0,0,0], [255,255,255,255]]]
if ips:
wc = [[ips.pop(0), [0,0,0,0]]]
for ip in ips:
for i in range(4):
wc[0][1][i] |= wc[0][0][i] ^ ip[i]
print(wc)
=> [[[192, 168, 0, 0], [0, 0, 255, 255]]]
"""
給一串可以預期整理成下方結果的IP
Network: 192.168.0.0, Wildcard Mask: 0.0.0.3
Network: 192.168.0.4, Wildcard Mask: 0.0.0.8
"""
ips = [[192,168,0,0],[192,168,0,1],[192,168,0,2],[192,168,0,3],[192,168,0,4],[192,168,0,12]]
from collections import defaultdict
wc = defaultdict(list)
"""
將 IP位置 做 summary
"""
def check(strIP, strIP2):
"""
只能有一個位置01同時出現
但如果是 * 符,二者沒有對上,就表示無法整合。
"""
dismatch = 0
pos = -1
for i in range(32):
if strIP[i] != strIP2[i]:
if strIP[i] == "*" or strIP2[i] == "*": return -1
dismatch += 1
pos = i
if dismatch == 2: return -1
return pos
for ip in ips:
strIP = "{:0>8}{:0>8}{:0>8}{:0>8}".format(*[bin(num)[2:] for num in ip]) # 換成 連續二進位 string
level = 0
pos = 0
while pos != -1 and wc[level]:
for j in range(len(wc[level])):
pos = check(strIP, wc[level][j][1])
if not pos == -1:
ip = wc[level].pop(j)[0]
strIP = strIP[:pos] + "*" + strIP[pos+1:]
level += 1
break
wc[level].append([ip, strIP])
"""
將 Summary 後的結果轉換回十進位格式
"""
result = []
for key in wc:
for NW in wc[key]:
NW[1] = NW[1].replace("1", "0").replace("*", "1")
result.append([NW[0], [int(NW[1][0:8],2), int(NW[1][8:16],2),int(NW[1][16:24],2),int(NW[1][24:32],2)]])
"""
將十進位的資料型態換成字串
"""
for each in sorted(result):
Network = ".".join([str(num) for num in each[0]])
WildcardMask = ".".join([str(num) for num in each[1]])
print("Network: {:}, Wildcard Mask: {:}".format(Network, WildcardMask))
Leetcode題解 Python & C#:六月挑戰DAY17 Surrounded Regions
Python
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if not board or not board[0]: return
excludePos = set()
rows = len(board)
cols = len(board[0])
def searchExclude(y, x):
if y = rows: return
if x = cols: return
if board[y][x] == "O" and (y,x) not in excludePos:
excludePos.add((y,x))
searchExclude(y-1, x)
searchExclude(y+1, x)
searchExclude(y, x-1)
searchExclude(y, x+1)
for y in range(rows):
searchExclude(y, 0)
searchExclude(y, cols-1)
for x in range(cols):
searchExclude(0, x)
searchExclude(rows-1, x)
for x in range(1, cols-1):
for y in range(1, rows-1):
if board[y][x] == "O" and (y,x) not in excludePos:
board[y][x] = "X"
C#
public class Solution {
public int rows;
public int cols;
public HashSet excludePos;
public void Solve(char[][] board) {
rows = board.Length;
if(rows == 0){return;}
cols = board[0].Length;
if(cols == 0){return;}
excludePos = new HashSet();
for(int y = 0; y < rows; y++)
{
SearchExcluded(board, y, 0);
SearchExcluded(board, y, cols-1);
}
for(int x = 0; x < cols; x++)
{
SearchExcluded(board, 0, x);
SearchExcluded(board, rows-1, x);
}
for(int y = 0; y < rows; y++)
{
for(int x = 0; x < cols; x++)
{
if(board[y][x] == 'O' && !excludePos.Contains((y, x)))
{
board[y][x] = 'X';
}
}
}
}
public void SearchExcluded(char[][] board, int y, int x) {
if(y = rows){return;}
if(x = cols){return;}
if(board[y][x] == 'O' && !excludePos.Contains((y, x)))
{
excludePos.Add((y, x));
SearchExcluded(board, y-1, x);
SearchExcluded(board, y+1, x);
SearchExcluded(board, y, x-1);
SearchExcluded(board, y, x+1);
}
}
}
JN的CCNA: 如何使用
這裡依照 《CCCNA 200-301 Official Cert Guide》 這本書的目錄做章節的分類,這使得照這裡的步驟去學習是與官方指南是一致的。所以只要一回回都確實完成,就能含蓋所有範圍。
每個章節(Charpter)可以分成三個部分︰
「學習內容」:
如果有書籍或其他來源沒有寫仔細的部分,我就會補充,否則只會放上出處。這裡會按照推薦順序排列,越好的會排在前面,多寡不一定,但最少一定會有書籍。
「實作練習」:
搭配《Cisco Packet Tracer》作練習,使用的版本為「7.3」。實作可分為二種:解說型、演練型。解說型主要目的為配合當節內容作「觀察」,注重各時刻的狀況變化;演練型的會有幾種:單項設定、除錯、多項設定、設計。每個演練型的最後都要完成一些要求,如:ping通,或是切斷部分仍能正常運作。
「相關題目」:
會把題庫中相關的題目放到這裡, 針對考題內容作實作(如果有辦法的話)。
我建議每個章節分三個狀態,然後自己紀錄下來進度,確保每個部分都有完成。
JN的CCNA: 對學習CCNA的看法
前言 – – 對學習CCNA的看法 2020.06.13
我在 2020-06-12 考到了 CCNA 的證照。
有人覺得 CCNA 的證照很好考,也許是,因為只要把「題庫」背熟,背多分,就能考過。但能考過是一回事,要考滿分又是另外一回事。2020年改版的CCNA題庫,因為還不成熟,各家答案並不一致,所以要是沒有強大的「實作」能力,只背是不可能明暸前因後果,找到一個能信服自己的答案(但不一定是正確的)。
總之,如果在台灣考,選用某中文論壇(hh)的題庫,正確率高,範圍精準,品質也好。但是我覺得還是有美中不足的地方,就是有一些關鍵敘述是漏掉的,那會「嚴重」影響解題。這現象在各版現有我看過的題庫,都有出現。
我認為不必花錢買題庫,因為不能保障買到的品質,更不能買到自己到題目會有深刻的理解。只有腳踏實地,一個個篇章逐一擊破,拿到證書才能稱上實質合格的CCNA。
CCNA的考試範圍是很大的,官方書籍(ccna certification study guide)的頁數總和就有千頁以上!新版合併各範圍成一個 200-301,因此也把各範圍拉一些到書的後面章節,分數也佔了不少。那些篇章不是 router & switch ,就好像從頭從零開始,然後多半又屬於記憶性的。先不說能看完就算厲害的,但看完只是入門,不夠,需要實作,
講這麼多,我認為CCNA是需要很多時間去精熟的,培訓課程開66小時,但那只夠把要上的都粗略講一遍,除非夠聰明,不然很難一次就照單全收,且能夠互相搭配運用。除了上課之外,練習也是很重要的,大概也要再花66小時去練實作,實作會學到的跟用到的可能是CCNP或是CCIE級別的深度。這裡的實作不只是單一項目的設定,也可能包含一些情境式的設計,或是效率優化的配置,那會用到許多CCNA會講到的協定,使根基更穩固。
我也是有上班級的,課餘花了很多時間去探索那些CCNA範圍內的知識與其運作。有CCNA證照不代表那些該會的能做得出來,懂不懂,那一眼就看得出來。CCNA並不限制一定要上他們合作機構的課程才能考試,所以課程沒上完就能考證照,沒上課也可以考試。
有證照一定是加分,會做是門檻,「會不會做才是關鍵」。
真實的工作情況大部分都是TroubleShooting,而也只有多練,過程自己一定會有不小心(遺漏或打錯),思考可能是哪裡出了錯,去找出那些問題,並且解決掉,才有辦法去往高階去創建或維護大型且複雜的網路。
看到一些同學在練習時,一臉盲然,努力回想上次老師講了什麼指令,然後重頭輸入。他們學習充滿了挫折感,因為不知為何。一個「不小心」,就連TroubleShooting的能力都沒有,呆坐電腦前,因為他們的腦內世界沒有TroubleShooting指令,只有上課講到的指令。
這樣的學習方式是大錯特錯,我並不是嘲諷那些人或教學方式的死板,而且老師教得不錯。
「輸入指令絕對不是第一步!」
要先有一個期望或設計(目的地),然後再想說要輸什麼指令(決定交通方式),再輸入指令(前往目的地),檢查(有沒有到達正確的地方)。這也是寫程式語言的標準流程。
那些學得挫折的同學,大多都沒有第一步的概念,也沒有第二步的思考與選擇,所以連去哪都不清楚,自己在搭乘什麼也不清楚,當然,所以自己此時此刻身處何方是沒有概念的,內心可能有這種感受「我是誰?我在哪?我在幹嘛?」
又或者沒有能區分「設計」與「設定」的對錯。
「設計」沒有對錯,除非是不合規則的(如router二介面設計在同一網段)。
而「設定」是跟隨設計,設定才會有明顯的對錯分別,沒照設計或是不合規則就是錯的。
能夠按設計圖施工,設定完成一個結構的人,才是「工程師」。如果每一步都要等人發號施令,那只是「工人」。這也使我在教同學時,到底要把所有指令全講,或是提示部分讓他思考,最終培育出不同程度的能力。
總之,要培養一個明確的思維思路,我都稱之「程式邏輯」。難的不是指令背不起來,而是沒辦法想到與制定一個如SOP一步一步的概念,要是能想到,指令再補上,就套方法可以用到許多領域。
最後,我的目標是「CCIE」,而且還想要有二張,因此,
關於CCNA或CCNP的學習頁面會一直作整理(更新)直到我考完CCIE第二張的半年。
這是我的規劃,在這期間內,如果有任何問題或更新,我會「Best Effort」去做,要是有幫上忙,就給個支持或留個言。
Leetcode題解 Python & C#:六月挑戰DAY16 Validate IP Address
Python
class Solution:
def validIPAddress(self, IP: str) -> str:
deci = {*"0123456789"}
hexdeci = {*"0123456789abcdef"}
def checkIPv4(IP):
group = IP.split(".")
if len(group) != 4: return False
for seg in group:
if not(3 >= len(seg) >= 1): return False
if any([c not in deci for c in seg]): return False
if not(255 >= int(seg) >= 0): return False
if str(int(seg)) != seg: return False
return True
def checkIPv6(IP):
group = IP.lower().split(":")
if len(group) != 8: return False
for seg in group:
if not(4 >= len(seg) >= 1): return False
if any([c not in hexdeci for c in seg]): return False
return True
if checkIPv4(IP): return "IPv4"
if checkIPv6(IP): return "IPv6"
return "Neither"
Python(IP轉換版)
class Solution:
def validIPAddress(self, IP: str) -> str:
decimal = {*"0123456789"}
def covertIPv4(IP):
IPv4 = ""
seg = ""
segCount = 0
for c in IP:
if c == ".":
segCount += 1
if segCount >= 4 or not seg: return False
if len(seg) > 1 and seg[0] == '0': return False
seg = "{:0>8}".format(bin(int(seg))[2:])
if len(seg) > 8: return False
IPv4 += seg
seg = ""
elif c in decimal:
seg += c
else:
return False
if seg:
if len(seg) > 1 and seg[0] == '0': return False
seg = "{:0>8}".format(bin(int(seg))[2:])
if len(seg) > 8: return False
IPv4 += seg
return len(IPv4) == 32
hexadecimal = {*"0123456789abcdefABCDEF"}
def covertIPv6(IP):
IPv6 = ""
seg = ""
segCount = 0
for c in IP:
if c == ":":
segCount += 1
if segCount >= 8 or not seg: return False
seg = "{:0>16}".format(seg)
if len(seg) > 16: return False
IPv6 += seg
seg = ""
elif c in hexadecimal:
seg += "{:0>4}".format(bin(int(c, 16))[2:])
else:
return False
if seg:
seg = "{:0>16}".format(seg)
if len(seg) > 16: return False
IPv6 += seg
return len(IPv6) == 128
if covertIPv4(IP): return "IPv4"
if covertIPv6(IP): return "IPv6"
return "Neither"
Python(IP轉換合一版)
class Solution:
def validIPAddress(self, IP: str) -> str:
decimal = {*"0123456789"}
hexadecimal = {*"0123456789abcdef"}
def covertIP(strIP, Segs, PerSegBit, Carry, Delimiter):
def addSeg(IP, seg):
if segCount >= Segs or not seg: return False
if Delimiter == "." and len(seg) > 1 and seg[0] == '0': return False
if Delimiter == ":" and len(seg) > 4: return False
try:
seg = ("{:0>"+str(PerSegBit)+"}").format(bin(int(seg, len(Carry)))[2:])
except:
return False
if len(seg) > PerSegBit: return False
return IP + seg
IP = seg = ""
segCount = 0
for c in strIP.lower():
if c == Delimiter:
segCount += 1
IP = addSeg(IP, seg)
if not IP: return False
seg = ""
elif c in Carry:
seg += c
else:
return False
if not seg: return False
IP = addSeg(IP, seg)
if not IP: return False
return len(IP) == Segs * PerSegBit
if covertIP(IP, 4, 8, decimal, "."): return "IPv4"
if covertIP(IP, 8, 16, hexadecimal, ":"): return "IPv6"
return "Neither"
C#
public class Solution {
public string ValidIPAddress(string IP) {
if(IsIPv4(IP)){return "IPv4";}
if(IsIPv6(IP)){return "IPv6";}
return "Neither";
}
private bool IsIPv4(string IP) {
var parts = IP.Split('.');
if(parts.Length != 4){return false;}
int dec = 0;
foreach(var part in parts)
{
if(!(Int32.TryParse(part, out dec))){return false;}
if(dec 255 || (dec.ToString().Length != part.Length)){return false;}
}
return true;
}
private bool IsIPv6(string IP) {
var parts = IP.Split(':');
if(parts.Length != 8){return false;}
int hex;
foreach(var part in parts)
{
if(part.Length > 4){return false;}
if(!Int32.TryParse(part,
System.Globalization.NumberStyles.HexNumber,
null,
out hex)){return false;}
if(hex < 0){return false;}
}
return true;
}
}
TestCase
"1.1.1.01"
"01.01.01.01"
"001.001.001.001"
"301.301.301.301"
"12..33.4"
"1.0.1."
"1.-1.1.1"
"0.0.0.0"
"172.16.254.1"
"256.256.256.256"
"2001:0db8:85a3:0:0:8A2E:0370:7334"
"2001:0db8:85a3::8A2E:0370:7334"
"2001:db8:85a3:0:0:8A2E:0370:7334"
"20EE:FGb8:85a3:0:0:8A2E:0370:7334"
"2001:0db8:85a3:00000:0:8A2E:0370:7334"
"1081:db8:85a3:01:-0:8A2E:0370:7334"
"2001:0db8:85a3:0:0:8A2E:0370:7334:"
Leetcode題解 Python:Maximum Frequency Stack
Python
class FreqStack:
def __init__(self):
self.count = defaultdict(int)
self.freq = defaultdict(list)
self.MaxFreq = 0
def push(self, x: int) -> None:
self.count[x] += 1
self.freq[self.count[x]].append(x)
self.MaxFreq = max(self.MaxFreq, self.count[x])
def pop(self) -> int:
num = self.freq[self.MaxFreq].pop()
self.count[num] -= 1
if not self.freq[self.MaxFreq]: self.MaxFreq -= 1
return num



















