算法——查找一个ip地址数组中,出现次数最多的ip

一道算法题

找出一组ip地址中,出现次数最多的ip,例:
输入
["192.168.12.32", "192.168.0.32", "192.168.12.32"]
输出
"192.168.12.32"

暴力破解法(优化了一下)

function filterIp(ipArr) {
    let maxIp = '';
    let maxCount = 0;
    for(let i = 0; i < ipArr.length; i++) {
        // 优化一下,如果当前ip等于maxIp则跳过本次统计
        if(maxIp === ipArr[i]){
            continue;
        }
        let cur = ipArr[i];
        let sum = 0;
        for(let j = 0; j < ipArr.length; j++) {
            if(cur === ipArr[j]){
                sum++;
            }
        }
        if(sum > maxCount) {
            maxCount = sum;
            maxIp = cur;
        }
    }

    return maxIp;
}

哈希表记录已被统计过了的ip

function filterIp(ipArr) {
    const map = {};
    for(let i = 0; i < ipArr.length; i++) {
        // 如果map中存在当前ip的key值,则表示该ip已经被统计过了。
        if(map[ipArr[i]]){
            continue;
        }

        let cur = ipArr[i];
        let sum = 0;

        // 从 i 开始,i 之前的一定是被统计过了的
        for(let j = i; j < ipArr.length; j++) {
            if(cur === ipArr[j]){
                sum++;
            }
        }
        // 写入map中
        map[cur] = sum;
    }

    let max = 0;
    let maxIp= '';
    for(let key in map){
        if(map[key] > max){
            max = map[key];
            maxIp= key;
        }
    }
    return maxIp;
}

字典树搜索

class Node {
    constructor(data){
        this.data = data;
    }

    data = '';
    count = 1;
    leaf = [];

    addLeaf(leaf) {
        this.leaf.push(leaf);
    }
    findLeaf(data) {
        for(let i = 0; i < this.leaf.length; i++) {
            if(this.leaf[i].data === data){
                return this.leaf[i];
            }
        }
        return null;
    }
    addCount(){
        this.count++;
    }
}

function createIpTree(ipArr){
    // 根节点为空
    let root = new Node('');
    for(let i = 0; i < ipArr.length; i++){
        let pointer = root;
        ipArr[i].split('.').forEach(item => {
            let includesLeaf = pointer.findLeaf(item);
            if(includesLeaf){
                includesLeaf.addCount();
                pointer = includesLeaf;
            } else {
                let node = new Node(item);
                pointer.addLeaf(node);
                pointer = node;
            }
        })
    }

    return root;
}

function depthFirstSearch(pointer) {
    let maxLeaf = pointer.leaf[0];
    for(let i = 0; i < pointer.leaf.length; i++) {
        if(pointer.leaf[i].count > maxLeaf.count){
            maxLeaf = pointer.leaf[i];
        }
    }
    return maxLeaf;
}

function filterIp(ipArr){
    // 创建字典树
    const ipTree = createIpTree(ipArr);

    // 深度优先搜索字典树,找出每个节点 count 最大的叶子,向下寻找
    let pointer = ipTree;
    let strArr = [];
    while(pointer.leaf.length) {
        let maxLeaf = depthFirstSearch(pointer);
        pointer = maxLeaf;
        strArr.push(maxLeaf.data);
    }

    return strArr.join('.');
}

mock数据 ip池 长度为3500 

字典树的平均时间居然是 0.1ms

字典树居然最慢?????

可能更大的数据量下字典树更快吧?

哈希表我可能用的不太好,我感觉还有优化方法,不过没有深入去想了。

可能还有别的方法,不过我暂时就想到这三个了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值