题解 | #代理服务器#
代理服务器
https://www.nowcoder.com/practice/1284469ee94a4762848816a42281a9e0
package main import ( "fmt" ) func main() { proxyMap := make(map[string]struct{}) serverList := make([]string, 0) shot := "" empty := struct{}{} // 模块A 读代理服务器 n := 0 _, _ = fmt.Scan(&n) for i := 0; i < n; i++ { var proxy string _, _ = fmt.Scan(&proxy) proxyMap[proxy] = empty if n == 1 { // 仅为 1 考虑命中 shot = proxy } } // 模块B 读目标服务器 m := 0 _, _ = fmt.Scan(&m) for i := 0; i < m; i++ { var next string _, _ = fmt.Scan(&next) serverList = append(serverList, next) if shot != "" && shot == next { // 仅为 1 且命中,则返回不对 fmt.Print(-1) return } } // 模块 C 贪心遍历 visitedMap := make(map[string]struct{}) visited := 0 count := 0 for _, server := range serverList { _, ok := proxyMap[server] if ok { _, isVisited := visitedMap[server] if !isVisited { visitedMap[server] = empty visited++ } if visited == n { count++ visited = 1 visitedMap = map[string]struct{}{server: empty} } } } fmt.Print(count) }
A: 遍历读取代理服务器,这里我做了个小技巧,分析题目要求,有返回-1的可能,且说明了输入的代理服务器各不相同,那只可能是 “只有一个代理服务器,且它在访问列表出现了”,这种情况我用了个 shot 变量保存
B : 遍历读取 目标服务器,使用数组保存一下返回的顺序。如果 shot 不是的,说明只有一个代理服务器,如果与此同时命中了shot,说明应该返回 -1 终止程序了
3: 核心算法区
C :我这里用了个新变量 visitedMap 来保存每个代理的使用情况,visited作为访问了多少个代理的数量,实际上如果想节省空间,也可以用proxyMap,但是时间复杂度会上升。
具体内容是遍历目标服务器列表,访问到存在于“代理服务器”中元素的时候,将,判断是不是所有代理都访问过了,不是就忽略
当所有代理都访问过时: 视为之前一直在使用最后代理服务器,遇到了该切换了,需要进行以下操作,清空访问情况和代理服务器访问次数,将最后一个代理服务器视为已访问,切换次数 + 1
举例 1
代理 A, B, C 访问 T, H, L, A, E, B
开始遍历的时候,还不知道第一个应该用什么服务器, count = 0, visit = 0
THL不存在于 代理服务器,无视
到达 A 时, A还没有访问过,先标记。此时访问记录:visit = 1, visitedMap 有 A
E 忽略, 到达 B 时, B 还没有访问过,先标记。此时访问记录:visit = 2, visitedMap 有 A、B
遍历结束,还有 C 没有访问过,ok,C 就是那个可以从头用到尾的,不用切换,所以 count 一直为 0, 输出 0
举例 2
代理 A, B, C 访问 T, C, L, A, E, B, T, Y
前面同理,到达 B 的时候都 C A 用过了,那就认为访问 T, C, L, A, E 都在用 B,到 B 切换了,具体使用 C 还是 A 看后面,当前操作是 切换次数 + 1 -> 清空使用记录和使用次数 -> 视为 B 使用了, 使用次数 + 1
遍历结束,最后时刻只有 B 被使用,说明 B C和 B A 两种使用路径都可行,切换 1 次