【Py/Java/C++三种语言OD独家2024E卷真题】20天拿下华为OD笔试之【模拟】2024E-IPv4地址转换成整数【欧弟算法】全网注释最详细分类最全的华为OD真题题解

可上 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过)

文章目录

  • 相关推荐阅读
  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 补充说明
    • 示例一
      • 输入
      • 输出
    • 示例二
      • 输入
      • 输出
  • 解题思路
    • 非法判断
    • 转换过程
  • 代码
    • python
    • java
    • cpp
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

相关推荐阅读

  • 【华为OD机考】2024D+E卷最全真题【完全原创题解 | 详细考点分类 | 不断更新题目】
  • 【华为OD笔试】2024D+E卷机考套题汇总【真实反馈,不断更新,限时免费】
  • 【华为OD笔试】2024D卷命题规律解读【分析300+场OD笔试考点总结】

从2024年8月14号开始,OD机考全部配置为2024E卷
注意几个关键点:

  1. 大部分的题目仍为往期2023A+B+C以及2024D的旧题。注意万变不离其宗,把方法掌握,无论遇到什么题目都可以轻松应对。
  2. 支持多次提交题目,以最后一次提交为准。可以先做200的再做100的,然后可以反复提交。
  3. E卷仍然为单机位+屏幕监控的形式进行监考。
  4. 进入考试界面新加入了这样一段话并且用红字标出,可以看出华子对作弊代考等行为是0容忍的,请各位同学认真学习,不要妄图通过其他违规途径通过考试。
    在这里插入图片描述

题目描述与示例

题目描述

存在一种虚拟IPv4地址,由4小节组成,除了第一小节的范围是1-128以外,其余三节的范围为0-255,以#号间隔,格式如下:

(1~128)#(0~255)#(0~255)#(0~255)

例如:

128#0#255#255`,转换为`32`位整数的结果为`2147549183(0x8000ffff)
1#0#0#0`,转换为`32`位整数的结果为`16777216(0x01000000)

请利用这个特性把虚拟IPv4地址转换为一个32位的整数,IPv4地址以字符串形式给出,要求每个IPvV4地址只能对应到唯一的整数上。

如果是非法IPv4,输出字符串"invalid IP"

输入描述

输入一行,虚拟IPv4地址格式字符串

输出描述

输出一行,按照要求输出整型或者特定字符

补充说明

输入不能确保是合法的IPv4地址,需要对非法IPv4 (空串,含有IP地址中不存在的字符,非合法的#分十进制,十进制整数不在合法区间内)进行识别,返回特定错误。

示例一

输入

100#101#1#5

输出

1684340997

示例二

输入

1#2#3

输出

invalid IP

解题思路

非法判断

对于输入的原字符串s,我们可以很方便地使用split()方法,以"#"为分隔符,将其分割为一个字符串列表IPv4_lst。然后对IPv4_lst考虑以下特殊情况:

  1. IPv4_lst长度不为4
  2. IPv4_lst中存在某一个字符串,不是纯数字
  3. IPv4_lst[0]即第一小节的取值范围不是1-128
  4. IPv4_lst[1]IPv4_lst[2]IPv4_lst[3]即第二、三、四小节的取值范围不是0-255

如果满足以上任何一种情况,输入均是一个非法字符,应该输出"invalid IP"

转换过程

对于一个合法的输入,我们需要理解将IPv4地址转换为整数是一个怎么样的过程,再将抽象的过程翻译成代码即可。属于一道非常纯粹的模拟题。

128#0#255#255转为2147549183(0x8000ffff)为例,其过程如下:

  1. #为分隔符,将原输入字符串分割为四个小节,为4个十进制数整数,即IPv4_lst = ["128", "0", "255", "255"]
IPv4_lst = input().split("#")
  1. 每个十进制整数都可以转换为一个两位的十六进制整数,即["80", "00", "ff", "ff"]
    1. 之所以是两位的十六进制整数,是因为取值范围的最大值,十进制的255 = 16 * 16 - 1,等于十六进制的"ff"最多为两位
    2. 直接使用hex()内置函数对原十进制数进行转换,将得到一个形如"0xFF"的字符串,其中前缀"0x"表示这是一个十六进制数。在这里需要使用切片对"0x"进行去除。
    3. 如果原十进制数小于16,那么转换后的数字位数为1,需要在前面补一个"0",才能使得其十六进制数的位数保持为2。譬如十进制的15,其十六进制为"f",位数为1位,需要在前面补一个"0"将其变成"0f"
IPv4_lst_16base = [hex(int(num)) for num in IPv4_lst]
IPv4_lst_16base = [item[2:] for item in IPv4_lst_16base]
IPv4_lst_16base = list(map(lambda x: "0" * (2-len(x))+x, IPv4_lst_16base))
  1. 将上述的4个两位的十六进制整数进行拼接,得到一个八位的十六进制数"8000FFFF"
IPv4_str_16base = "".join(IPv4_lst_16base)
  1. 将这个八位的十六进制数转化为十进制整数,得到答案2147549183
ans = int(IPv4_str_16base, base = 16)

代码

python

# 题目:2024E-IPv4地址转换成整数
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:模拟/进制转换
# 代码看不懂的地方,请直接在群上提问


# 将输入的字符串,以"#"为分隔符进行分割
# 得到一个长度为4的字符串数组IPv4_lst
IPv4_lst = input().split("#")
# 设置标记isError,初始化为False表示没有出现错误
isError = False

# 一些特殊情况的判断
# 如果IPv4_lst长度不为4,出现错误
if len(IPv4_lst) != 4:
    isError = True
# 如果IPv4_lst中包含不是数字的字符串,出现错误
elif not all(num.isdigit() for num in IPv4_lst):
    isError = True
# 第一小节的取值范围是1-128,如果不落在这个范围内,出现错误
elif int(IPv4_lst[0]) > 128 or int(IPv4_lst[0]) == 0:
    isError = True
# 第二、三、四小节的取值范围是0-255,如果不落在这个范围内,出现错误
elif not all(0 <= int(num) <= 255 for num in IPv4_lst[1:]):
    isError = True
# 剩余情况,才是符合要求的,可以做进制转换的字符串
else:
    # 将IPv4_lst中的十进制整数转化为10进制数,使用内置函数hex()
    IPv4_lst_16base = [hex(int(num)) for num in IPv4_lst]
    # 转换后每一个十六进制的字符串都会存在一个"0x"前缀,故要用切片操作进行去除
    IPv4_lst_16base = [item[2:] for item in IPv4_lst_16base]
    # 每一个十六进制数,长度必须是2,故不够2位的需要在前面补0,补齐成2位
    # 如十六进制的"5"需要改成"05"
    IPv4_lst_16base = list(map(lambda x: "0" * (2-len(x))+x, IPv4_lst_16base))
    # 将4个十六进制数合并成一个长度为8的字符串
    IPv4_str_16base = "".join(IPv4_lst_16base)
    # 将IPv4_str_16base转化为十进制数,使用内置函数int()
    ans = int(IPv4_str_16base, base = 16)
    # 输出答案
    print(ans)

if isError:
    print("invalid IP")

java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        scanner.close();

        String[] IPv4_lst = input.split("#");
        boolean isError = false;

        if (IPv4_lst.length != 4) {
            isError = true;
        } else if (!isAllDigits(IPv4_lst)) {
            isError = true;
        } else if (Long.parseLong(IPv4_lst[0]) > 128 || Long.parseLong(IPv4_lst[0]) == 0) {
            isError = true;
        } else if (!isInRange(IPv4_lst, 1, 3)) {
            isError = true;
        } else {
            StringBuilder IPv4_str_16base = new StringBuilder();

            for (String num : IPv4_lst) {
                String hexNum = Long.toHexString(Long.parseLong(num));
                if (hexNum.length() < 2) {
                    hexNum = "0" + hexNum;
                }
                IPv4_str_16base.append(hexNum);
            }

            long ans = Long.parseLong(IPv4_str_16base.toString(), 16);
            System.out.println(ans);
        }

        if (isError) {
            System.out.println("invalid IP");
        }
    }

    private static boolean isAllDigits(String[] arr) {
        for (String num : arr) {
            if (!num.matches("\\d+")) {
                return false;
            }
        }
        return true;
    }

    private static boolean isInRange(String[] arr, int start, int end) {
        for (int i = start; i <= end; i++) {
            long num = Long.parseLong(arr[i]);
            if (num < 0 || num > 255) {
                return false;
            }
        }
        return true;
    }
}

cpp

#include 
#include 
#include 

using namespace std;

bool areAllDigits(const vector<string>& arr) {
    for (const string& num : arr) {
        for (char c : num) {
            if (!isdigit(c)) {
                return false;
            }
        }
    }
    return true;
}

bool areAllInRange(const vector<string>& arr, long start, long end) {
    for (long i = start; i <= end; i++) {
        long num = stol(arr[i]);
        if (num < 0 || num > 255) {
            return false;
        }
    }
    return true;
}

int main() {
    string input;
    getline(cin, input);
    stringstream ss(input);

    vector<string> IPv4_lst;
    string segment;
    while (getline(ss, segment, '#')) {
        IPv4_lst.push_back(segment);
    }

    bool isError = false;

    if (IPv4_lst.size() != 4) {
        isError = true;
    } else if (!areAllDigits(IPv4_lst)) {
        isError = true;
    } else if (stol(IPv4_lst[0]) > 128 || stol(IPv4_lst[0]) == 0) {
        isError = true;
    } else if (!areAllInRange(IPv4_lst, 1, 3)) {
        isError = true;
    } else {
        vector<string> IPv4_lst_16base;

        for (const string& num : IPv4_lst) {
            stringstream hexStream;
            hexStream << hex << stol(num);
            string hexNum = hexStream.str();
            if (hexNum.length() < 2) {
                hexNum = "0" + hexNum;
            }
            IPv4_lst_16base.push_back(hexNum);
        }

        string IPv4_str_16base = "";
        for (const string& num : IPv4_lst_16base) {
            IPv4_str_16base += num;
        }

        long ans = stol(IPv4_str_16base, nullptr, 16);
        cout << ans << endl;
    }

    if (isError) {
        cout << "invalid IP" << endl;
    }

    return 0;
}

时空复杂度

时间复杂度:O(1)。常数级别的操作。

空间复杂度:O(1)。常数级别的内存。


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务300+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,模拟,#,数学,java,c++,华为od,算法,leetcode,python)