#####题目
1. FlowStatsSystem
在一台计算机上运行着多个网络程序的进程,每个进程可以绑定多个端口,每个端口同一时刻只能被绑定在一个进程上,每个端口在绑定成功后可以接收网络报文。
请设计一个流量统计的简易系统,实现下面接口:
FlowStatsSystem() – 系统初始化。
bindport(int pid,int port) - 绑定一个端口port到进程pid上,如果此port已经被绑定,则绑定失败并且返回false;否则绑定成功,并返回true。
unbindPort(int port) - 解除端口port和进程的绑定关系。如果此端口已被绑定,则解除绑定,已接收的报文不清零,并返回true;否则直接返回false。
recvPacket(int port,int packetLen) -端口port上收到一段长度为packetLen的报文,
如果端口port没有被绑定在任何一个进程上,则直接返回0,报文丢弃。
如果端口port已绑定在某个进程上,则这个进程接收的[报文总长度]累加packetLen,然后返回[报文总长度]。
statPacket(int topNum) - 统计收到报文总长度最大的topNum个进程,并按如下规则返回这些进程pid的列表:
对于未接收过报文的进程,不统计。
优先按进程接收的[报文总长度]降序;若总长度相同,再按进程pid升序。
若符合条件的进程数不足topNum,按实际数量返回;若无符合条件的,返回空列表[]。
输入
每行表示一个函数调用,初始化函数仅首行调用一次,累计函数调用不超过100次。
1<=port<=65535,1<=pid<=100000,1<=packetLen<=100000,1<=topNum<=5
输出
答题时按照函数/方法原型中的要求(含返回值)进行实现,输出由框架完成(其中首行固定输出null)
思路:
注意到pid对应报文长度不会被清除。所以题目简化为 pid2Len,port2pid两个映射。 其中pid2Len为只增加的
关键问题就是排序
package main
import (
"fmt"
"sort"
)
type PidSystem struct {
pid int
packetLen int
}
type FlowStatsSystem struct {
ZERO int
portMap map[int]int // port => pid
pidMap map[int]*PidSystem // pid => pidSystem
}
func NewFlowStatsSystem() *FlowStatsSystem {
return &FlowStatsSystem{
ZERO: 0,
portMap: make(map[int]int),
pidMap: make(map[int]*PidSystem),
}
}
func (f *FlowStatsSystem) bindPort(pid int, port int) bool {
if _, ok := f.portMap[port]; ok {
return false
} else {
f.portMap[port] = pid
return true
}
}
func (f *FlowStatsSystem) unbindPort(port int) bool {
if _, ok := f.portMap[port]; ok {
delete(f.portMap, port)
return true
}
return false
}
func (f *FlowStatsSystem) recvPacket(port int, packetLen int) int {
if _, ok := f.portMap[port]; !ok {
return f.ZERO
}
pid := f.portMap[port]
pidSystem, ok := f.pidMap[pid]
if !ok {
pidSystem = &PidSystem{pid: pid, packetLen: f.ZERO}
f.pidMap[pid] = pidSystem
}
pidSystem.packetLen += packetLen
return pidSystem.packetLen
}
func (f *FlowStatsSystem) statPacket(topNum int) []int {
var filterPid []*PidSystem
for _, v := range f.pidMap {
if v.packetLen > 0 {
filterPid = append(filterPid, v)
}
}
if len(filterPid) == f.ZERO {
return []int{}
}
sort.Slice(filterPid, func(i, j int) bool {
if filterPid[i].packetLen == filterPid[j].packetLen {
return filterPid[i].pid < filterPid[j].pid
}
return filterPid[i].packetLen > filterPid[j].packetLen
})
res := make([]int, len(filterPid))
for i, v := range filterPid {
res[i] = v.pid
}
if len(res) > topNum {
return res[:topNum]
} else {
return res
}
}
func main() {
flowStatsSystem := NewFlowStatsSystem()
flowStatsSystem.bindPort(23215, 443)
flowStatsSystem.bindPort(23215, 443)
flowStatsSystem.bindPort(23215, 3306)
flowStatsSystem.bindPort(23216, 3306)
flowStatsSystem.bindPort(23216, 80)
flowStatsSystem.recvPacket(3306, 100)
flowStatsSystem.recvPacket(443, 200)
flowStatsSystem.recvPacket(80, 300)
flowStatsSystem.unbindPort(443)
ints := flowStatsSystem.statPacket(2)
fmt.Println(ints)
}
#### 感受
1. 设计能力薄弱,只能设计到portMap(port => pid),但是没办法pidMap(pid => pidSystem)中使用 map结构体
2. 经典排序Top问题, 先排序,然后取top(如果len小于top,取全部)// 默写100次
3. 1->n; n->1 主键都在n里面 n->m 需要新增一张表
标签:return,int,pid,端口,filterPid,packetLen,进程,设计,port
From: https://www.cnblogs.com/gongxianjin/p/17899039.html