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

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

相关推荐阅读

题目练习网址:https://www.algomooc.com/problem/P2508

视频直播讲解:

2023/08/19 真题讲解

2024/09/28 真题讲解(2024E卷)

题目描述与示例

题目描述

存在一种虚拟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

解题思路

本题涉及的进制转换和Python内置函数的知识可查看算法题中常用数学概念、公式、方法汇总Python常用内置函数、方法、技巧汇总相关内容。

非法判断

对于输入的原字符串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"。对应代码

# 将输入的字符串,以"#"为分隔符进行分割
# 得到一个长度为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:
pass

转换过程

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

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

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

把所有代码组织在一起就是答案了。

代码

Python

# 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
# 地址:https://www.odalgo.com
# 华为OD机试刷题网站:https://www.algomooc.com
# 添加微信 278166530 获取华为 OD 笔试真题题库和视频
# 题目:2023B/2024E/2025C-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;
}
}

C++

#include <iostream>
  #include <sstream>
    #include <vector>
      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;
              }

C

#include <stdio.h>
  #include <stdlib.h>
    #include <string.h>
      #include <ctype.h>
        /* 判断所有段均为数字(非空,且每个字符都是 '0'..'9') */
        int areAllDigits(char *arr[], int len) {
        for (int i = 0; i < len;
        ++i) {
        char *s = arr[i];
        if (s == NULL || *s == '\0') return 0;
        for (const char *p = s;
        *p;
        ++p) {
        if (!isdigit((unsigned char)*p)) return 0;
        }
        }
        return 1;
        }
        /* 判断 arr[start..end] 是否都在 [0,255] */
        int areAllInRange(char *arr[], int start, int end) {
        for (int i = start; i <= end;
        ++i) {
        char *endptr = NULL;
        unsigned long v = strtoul(arr[i], &endptr, 10);
        if (*arr[i] == '\0' || *endptr != '\0') return 0;
        // 非法数字串
        if (v >
        255UL) return 0;
        }
        return 1;
        }
        int main(void) {
        /* 读取整行输入,例如: "a#b#c#d" */
        char line[1024];
        if (!fgets(line, sizeof(line), stdin)) return 0;
        /* 去掉末尾换行符 */
        size_t L = strlen(line);
        if (L >
        0 &&
        (line[L - 1] == '\n' || line[L - 1] == '\r')) {
        line[L - 1] = '\0';
        }
        /* 按 '#' 分割成 4 段 */
        char *parts[4] = {
        0
        };
        int cnt = 0;
        char *tok = strtok(line, "#");
        while (tok && cnt <
        4) {
        parts[cnt++] = tok;
        tok = strtok(NULL, "#");
        }
        /* 若还有多余段,或不足 4 段,均视为错误 */
        if (tok != NULL) cnt = 5;
        // 超过 4 段
        int isError = 0;
        /* 段数必须等于 4 */
        if (cnt != 4) {
        isError = 1;
        }
        /* 所有段必须为纯数字 */
        else if (!areAllDigits(parts, 4)) {
        isError = 1;
        }
        /* 首段范围检查:1..128(==0 或 >128 视为无效) */
        else {
        char *endptr = NULL;
        unsigned long first = strtoul(parts[0], &endptr, 10);
        if (*parts[0] == '\0' || *endptr != '\0' || first == 0UL || first >
        128UL) {
        isError = 1;
        }
        /* 其余三段范围检查:0..255 */
        else if (!areAllInRange(parts, 1, 3)) {
        isError = 1;
        }
        }
        if (!isError) {
        /* 将四段分别转为两位16进制(不足补0),拼接成8位16进制串 */
        char hexstr[9];
        // 8位十六进制 + 终止符
        int pos = 0;
        for (int i = 0; i <
        4;
        ++i) {
        unsigned long v = strtoul(parts[i], NULL, 10);
        // 0..255
        /* 写入两位十六进制到 hexstr 的正确位置(小写) */
        /* %02lx 会保证两位,不足补0 */
        char tmp[3];
        snprintf(tmp, sizeof(tmp), "%02lx", v);
        hexstr[pos++] = tmp[0];
        hexstr[pos++] = tmp[1];
        }
        hexstr[pos] = '\0';
        /* 将 8 位十六进制串解析为十进制整数并输出 */
        unsigned long long ans = strtoull(hexstr, NULL, 16);
        printf("%llu\n", ans);
        } else {
        printf("invalid IP\n");
        }
        return 0;
        }

Node JavaScript

const fs = require('fs');
const line = fs.readFileSync(0, 'utf8').trim();
const parts = line.split('#');
let isError = false;
// 检查段数
if (parts.length !== 4) {
isError = true;
}
// 检查是否全为数字
function isAllDigits(arr) {
const re = /^\d+$/;
for (const s of arr) {
if (!re.test(s)) return false;
}
return true;
}
if (!isError &&
!isAllDigits(parts)) {
isError = true;
}
// 检查范围:首段 1..128,其余段 0..255
function inRangeOthers(arr, start, end) {
for (let i = start; i <= end; i++) {
const v = Number(arr[i]);
if (!(v >= 0 && v <= 255)) return false;
}
return true;
}
if (!isError) {
const first = Number(parts[0]);
if (first === 0 || first >
128) {
isError = true;
} else if (!inRangeOthers(parts, 1, 3)) {
isError = true;
}
}
if (!isError) {
// 转 16 进制并拼接
let hex = '';
for (const s of parts) {
const v = Number(s);
const h = v.toString(16);
hex += h.length <
2 ? ('0' + h) : h;
}
// 解析为十进制并输出
const ans = parseInt(hex, 16);
console.log(ans);
} else {
console.log('invalid IP');
}

Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// 判断数组每段是否均为十进制数字串(非空,且全部为 '0'..'9')
func isAllDigits(arr []string) bool {
for _, s := range arr {
if len(s) == 0 {
return false
}
for i := 0; i <
len(s); i++ {
if s[i] <
'0' || s[i] >
'9' {
return false
}
}
}
return true
}
// 检查 arr[start..end] 是否都在 [0,255]
func inRange(arr []string, start, end int) bool {
for i := start; i <= end; i++ {
v, err := strconv.ParseUint(arr[i], 10, 64)
if err != nil {
return false
}
if v >
255 {
return false
}
}
return true
}
func main() {
in := bufio.NewReader(os.Stdin)
line, _ := in.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, "#")
isError := false
// 段数必须为 4
if len(parts) != 4 {
isError = true
}
// 全为数字
if !isError &&
!isAllDigits(parts) {
isError = true
}
// 范围检查
if !isError {
first, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil || first == 0 || first >
128 {
isError = true
} else if !inRange(parts, 1, 3) {
isError = true
}
}
if !isError {
// 转为 16 进制并拼接
hex := make([]byte, 0, 8)
for _, s := range parts {
v, _ := strconv.ParseUint(s, 10, 64)
h := strings.ToLower(strconv.FormatUint(v, 16))
if len(h) <
2 {
hex = append(hex, '0')
}
hex = append(hex, h...)
}
// 解析 16 进制串为十进制整数
ans, err := strconv.ParseUint(string(hex), 16, 64)
if err != nil {
fmt.Println("invalid IP")
return
}
fmt.Println(ans)
} else {
fmt.Println("invalid IP")
}
}

时空复杂度

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

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


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

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

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

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

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

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

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

posted @ 2025-08-16 11:20  wzzkaifa  阅读(42)  评论(0)    收藏  举报