根据IP查找城市 - 华为OD统一考试

news2024/11/15 13:50:06

OD统一考试

题解: Java / Python / C++

alt

题目描述

某业务需要根据终端的IP地址获取该终端归属的城市,可以根据公开的IP地址池信息查询归属城市。

地址池格式如下:

城市名=起始IP,结束IP

起始和结束地址按照英文逗号分隔,多个地址段采用英文分号分隔。

比如:
City1=1.1.1.1,1.1.1.2;City1=1.1.1.11,1.1.1.16;City2=3.3.3.3,4.4.4.4;City3=2.2.2.2,6.6.6.6。

一个城市可以有多个IP段,比如City1有2个IP段。

城市间也可能存在包含关系,比如City3的IP段范围包括City2的IP段范围。

现在要根据输入的IP列表,返回最佳匹配的城市列表。

注:最佳匹配即可包含待查询IP且长度最小的IP段,比如例子中的
3.4.4.4的最佳匹配是City2=3.3.3.3,4.4.4.4;
5.5.5.5的最佳匹配是City3=2.2.2.2,6.6.6.6。

输入描述

输入共2行。

第一行为城市的IP段列表,多个IP段采用英文分号’;'分隔,IP段列表最大不超过500000。

城市名称只包含英文字母、数字和下划线,最多不超过100000个。

IP段包含关系可能有多层,但不超过100层。

第二行为查询的IP列表,多个IP采用英文逗号’,'分隔,最多不超过10000条。

输出描述

最佳匹配的城市名列表,采用英文逗号,分隔,城市列表长度应该跟查询的IP列表长度一致。

示例1

输入:
City1=1.1.1.1,1.1.1.2;City1=1.1.1.11,1.1.1.16;City2=3.3.3.3,4.4.4.4;City3=2.2.2.2,6.6.6.6
1.1.1.15,3.3.3.5,2.2.2.3

输出:
City1,City2,City3

题解

这道题目涉及到对IP地址范围的处理和匹配,可以通过以下步骤解决:

  1. 将输入的IP范围按照起始IP排序,以便后续的查找操作。
  2. 对于每个待查询的IP,从排序后的IP范围列表中找到满足条件的最佳匹配,即包含待查询IP且长度最小的IP段。
  3. 输出最佳匹配的城市列表。

在此题目中为了方便的对 ip 进行处理,代码中将字符串的ip转成了等价的正整数。

具体实现中,可以使用类来表示IP范围,然后对IP范围列表进行排序。

在查询时,遍历排序后的IP范围列表,找到最佳匹配的城市。

Java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class IpRange {
    public String city;
    public long startIp;
    public long endIp;

    public IpRange(String city, long startIp, long endIp) {
        this.city = city;
        this.startIp = startIp;
        this.endIp = endIp;
    }
}

/**
 * @author code5bug
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        List<IpRange> ipRanges = new ArrayList<>();

        // 读取 IP 范围并进行排序
        String[] rangeInputs = scanner.nextLine().split(";");
        for (String rangeInput : rangeInputs) {
            String[] parts = rangeInput.split("=");
            String city = parts[0];
            String[] ipRange = parts[1].split(",");
            long startIp = ipToLong(ipRange[0]), endIp = ipToLong(ipRange[1]);
            ipRanges.add(new IpRange(city, startIp, endIp));
        }
        ipRanges.sort((x, y) -> (int) (x.startIp - y.startIp));

        // 查询并输出结果
        String[] ipInputs = scanner.nextLine().split(",");
        List<String> results = new ArrayList<>();
        for (String ipInput : ipInputs) {
            results.add(findCity(ipRanges, ipToLong(ipInput)));
        }
        System.out.println(String.join(",", results));
    }

    /**
     * IP 字符串转成10进制的整数
     *
     * @param ip
     * @return
     */
    private static long ipToLong(String ip) {
        String[] ipParts = ip.split("\\.");
        return (0L | Integer.parseInt(ipParts[0]) << 24) |
                (Integer.parseInt(ipParts[1]) << 16) |
                (Integer.parseInt(ipParts[2]) << 8) |
                Integer.parseInt(ipParts[3]);
    }

    /**
     * 根据IP 查询归属城市, 返回最佳匹配城市名称(既满足条件且长度最小的IP段)
     *
     * @param ipRanges
     * @param ip
     * @return
     */
    private static String findCity(List<IpRange> ipRanges, long ip) {
        String city = "unknown";
        long cityLength = Long.MAX_VALUE;
        for (IpRange ipRange : ipRanges) {
            if (ipRange.startIp > ip) break;

            long length = ipRange.endIp - ipRange.startIp + 1;
            if (ipRange.startIp <= ip && ip <= ipRange.endIp && length < cityLength) {
                cityLength = length;
                city = ipRange.city;
            }
        }

        return city;
    }
}


Python


from math import inf
import string


def ip_to_int(ip: string):
    """ IP 字符串转成10进制的整数 """
    ip_nums = list(map(int, ip.split('.')))
    return ip_nums[0] << 24 | ip_nums[1] << 16 | ip_nums[2] << 8 | ip_nums[3]


class IpRange:
    """ IP范围 """

    def __init__(self, city, start_ip, end_ip):
        self.start_ip = ip_to_int(start_ip)
        self.end_ip = ip_to_int(end_ip)
        self.city = city


ip_ranges = []
for sip in input().split(";"):
    city, iprange = sip.split("=")
    start_ip, end_ip = iprange.split(",")
    ip_ranges.append(IpRange(city, start_ip, end_ip))

# 根据 x.start_ip 升序 进行排序
ip_ranges.sort(key=lambda x: x.start_ip)


def find_city(ip):
    """ 根据IP 查询归属城市 """
    global ip_ranges

    # 返回最佳匹配城市名称(既满足条件且长度最小的IP段)
    city, city_length = "unknown", inf
    for it in ip_ranges:
        if it.start_ip > ip:
            break

        lenght = it.end_ip - it.start_ip + 1
        if it.start_ip <= ip <= it.end_ip and lenght < city_length:
            city_length = lenght
            city = it.city

    return city


rs = []
for sip in input().split(","):
    rs.append(find_city(ip_to_int(sip)))
print(",".join(rs))

C++

#include <bits/stdc++.h>

using namespace std;

class IpRange {
public:
    string city;
    long startIp;
    long endIp;

    IpRange(string city, long startIp, long endIp)
        : city(move(city)), startIp(startIp), endIp(endIp) {}
};

// IP 字符串转成10进制的整数
long ipToLong(const string& ip) {
    istringstream iss(ip);
    string token;
    long result = 0;
    while (getline(iss, token, '.')) {
        result = (result << 8) | stoi(token);
    }
    return result;
}

// 根据IP 查询归属城市, 返回最佳匹配城市名称(既满足条件且长度最小的IP段)
string findCity(const vector<IpRange>& ipRanges, long ip) {
    string city = "unknown";
    long cityLength = LONG_MAX;

    for (const auto& ipRange : ipRanges) {
        if (ipRange.startIp > ip) break;

        long length = ipRange.endIp - ipRange.startIp + 1;
        if (ipRange.startIp <= ip && ip <= ipRange.endIp && length < cityLength) {
            cityLength = length;
            city = ipRange.city;
        }
    }

    return city;
}


vector<string> split(const string &str, const char &delim) {
    vector<string> res;
    stringstream ss(str);
    string tmp;
    while (getline(ss, tmp, delim)) {
        if (!tmp.empty()) res.push_back(std::move(tmp));
    }
    return res;
}

int main() {
    vector<IpRange> ipRanges;

    // 读取 IP 范围并进行排序
    string inputLine;
    getline(cin, inputLine);

    vector<string> parts = split(inputLine, ';');
    for(string& part : parts) {
        vector<string> arr = split(part, '=');
        string city = arr[0];

        vector<string> ips = split(arr[1], ',');
        ipRanges.emplace_back(city, ipToLong(ips[0]), ipToLong(ips[1]));
    }

    sort(ipRanges.begin(), ipRanges.end(), [](const auto& x, const auto& y) {
        return x.startIp < y.startIp;
    });

    // 查询并输出结果
    getline(cin, inputLine);

    vector<string> results;
    for(auto& ip : split(inputLine,',')) {
        results.push_back(findCity(ipRanges, ipToLong(ip)));
    }


    for(int i=0; i<results.size(); i++) {
        if(i + 1 == results.size()) {
            cout << results[i] << endl;
        } else {
            cout << results[i] << ",";
        }
    }

    return 0;
}

‍❤️‍华为OD机试面试交流群每日真题分享): 加V时备注“华为od加群”

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1398367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

链表回文结构

链表回文结构 编写一个函数&#xff0c;检查输入的链表是否是回文的。 示例 1&#xff1a; 输入&#xff1a; 1->2 输出&#xff1a; false 示例 2&#xff1a; 输入&#xff1a; 1->2->2->1 输出&#xff1a; true 链表的回文结构&#xff0c;应该先找到中间节…

yum配置文件及NFS共享

一 yum配置文件及命令 1 /etc/yum.conf //主配置文件 2 /etc/yum.repos.d/*.repo //yum仓库文件位置 写错一个字母就不行&#xff0c;可以ping www.google.com 测试网络 3 /var/log/yum.log //日志文件 二 yum命令 1 [rootlocalhost ~…

Python项目——计算器(PySide6+Pyinstaller)

1、介绍 使用python编写一个计算器&#xff0c;可以实现基本的运算。【注】该项目最终还有一些细小的bug没有完善&#xff0c;例如符号可以一直输入。 2、实现 使用pyCharm创建一个新的项目。 2.1、设计UI 使用Qt designer设计一个UI界面&#xff0c;保存ui文件&#xff0…

electron-vite中的ipc通信

1. 概述 再electron中&#xff0c;进程间的通信通过ipcMain和ipcRenderer模块&#xff0c;这些通道是任意和双向的 1.1. 什么是上下文隔离进程 ipc通道是通过预加载脚本绑定到window对象的electron对象属性上的 2. 通信方式 2.1. ipcMain&#xff08;也就是渲染进程向主进…

福昕软件的使用

快捷操作 快捷键 快捷键功能备注Ctrl P打印 Ctrl W关闭 Ctrl B书签 鼠标放菜单栏&#xff0c;单击右键即可导入/导出 自定义菜单栏文件-->偏好设置-->文档 1、多实例&#xff1a;单击PDF后均重新打开一个新界面。

数字图像处理期末速成笔记

目录 一、基础知识二、相邻像素间基本关系三、图像增强方法1、直方图求解2、直方图均衡化3、直方图规定化4、图像平滑5、邻域平均法&#xff08;线性&#xff09;6、 中值滤波法&#xff08;分线性&#xff09;7、中值滤波与领域平均的异同8、4-邻域平滑法9、超限像素平滑法10、…

C++ BuilderXE关于FDQuery组件记录限制设定

这样修改就可以查询返回所有记录。 TFDQuery.RecordCount,或TDateSet.RecordCount只显示了可见的50条数据&#xff0c;但实际上数据的总量超过了这个数量。为了解决这个问题&#xff0c;我们可以通过更改TFDConection.FetchOptions.RecordCountMode属性为fmTotal&#xff0c;以…

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测效果一览基本介绍程序设计…

Elasticsearch 入门向使用

文章目录 ElasticSearch简介倒排索引安装(单节点)分词器kibana与Mysql概念上的对比索引库CRUD文档CRUDDSL查询相关性算分Function Score Query自定义算分Boolean Query 搜索结果处理排序分页高亮 数据聚合 aggregations自动补全数据同步集群 ElasticSearch 简介 Elasticsearc…

java SSM园林绿化管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM园林绿化管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

【论文阅读】GPT4Graph: Can Large Language Models Understand Graph Structured Data?

文章目录 0、基本介绍1、研究动机2、准备2.1、图挖掘任务2.2、图描述语言&#xff08;GDL&#xff09; 3、使用LLM进行图理解流程3.1、手动提示3.2、自提示 4、图理解基准4.1、结构理解任务4.1、语义理解任务 5、数据搜集5.1、结构理解任务5.2、语义理解任务 6、实验6.1、实验设…

Spark面试题

1. spark core 1.简述hadoop 和 spark的不同点&#xff08;为什么spark更快&#xff09;♥♥♥ shuffle都是需要落盘的&#xff0c;因为在宽依赖中需要将上一个阶段的所有分区数据都准备好&#xff0c;才能进入下一个阶段&#xff0c;那么如果一直将数据放在内存中&#xff0c…

ARM多核调度器DSU

1. 背景 从A75开始&#xff0c;ARM提出了一个新的多核心管理系统单元&#xff0c;叫做DSU(DynamIQ Shared Unit)。DSU的核心功能是控制CPU内核&#xff0c;使其成簇Cluster使用&#xff0c;簇内每一个核心可以单独开关、调整频率/电压&#xff0c;能效表现更佳&#xff0c;甚至…

手动正则删除console.log

依赖删除的可以先出去了 先得删除箭头函数里的 正则匹配不能直接删&#xff0c;如这种箭头函数&#xff0c;得先全局改了 然后正则 console.log(.*?) 选中》空着〉全局替换 最后删除 // 因为有的 console.log在代码块原来就是被空着状态&#xff0c; 所以也得全局为空替…

正则表达式..

1.字符串的合法检验 现在有一个字符串验证码 我们需要检验其的合法性 什么条件才能够使得字符串合法呢&#xff1f;就是6-10个字符串长度 并且以字母开头 并且其中由字母、数字、下划线构成 那么我们可以先通过自定义的方式进行检验 public class Main {public static void m…

通过Konva.js实现canvas列表滚动

列表可以通过Konva.js中的Rect来实现&#xff0c;通过group可以丰富列表的内容 在滚动方面&#xff0c;可以通过vue的scroll方法&#xff0c;通过rect中的move方法来修改y值即可 我这里设置的是一个透明的盒子在想要滚动的canvas上&#xff0c;这样就可以实现直接滚动canvas列…

K8s(七)四层代理Service

Service概述 Service在Kubernetes中提供了一种抽象的方式来公开应用程序的网络访问&#xff0c;并提供了负载均衡和服务发现等功能&#xff0c;使得应用程序在集群内外都能够可靠地进行访问。 每个Service都会自动关联一个对应的Endpoint。当创建一个Service时&#xff0c;Ku…

springboot109新闻稿件管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的新闻稿件管理系统 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获…

SpringMVC下半篇之整合ssm

4.ssm整合 4.1.创建表 CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT,name varchar(20) DEFAULT NULL,money double DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8;4.2.创建工程 4.3.pom.xml <?xml version"1.0" encoding&…

【图形学】颜色线性插值和Wu反走样算法

颜色线性插值 绘制一条颜色渐变的直线&#xff0c;直线上每一个点的颜色都来自端点颜色的线性插值。线性插值公式为 P ( 1 − t ) P s t a r t t P e n d P 是直线上任意一个点&#xff0c; P s t a r t 是直线的起点&#xff0c; P e n d 是直线的终点 对应直线上任意一点…