深入解析:20天拿下华为OD笔试之【模拟】2025C-IPv4地址转换成整数【Py/Java/C++/C/JS/Go六种语言OD独家2025C卷真题】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
可上 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)
文章目录
相关推荐阅读
- 【华为OD机考】2025C+2025B+2024E+D卷真题【完全原创题解 | 详细考点分类 | 不断更新题目】
- 【华为OD笔试】2025C+2025B+2024E+D卷真题机考套题汇总【真实反馈,不断更新,限时免费】
- 【华为OD笔试】2024E+D卷命题规律解读【分析500+场OD笔试考点总结】
- 【华为OD流程】性格测试选项+注意事项】
题目练习网址:https://www.algomooc.com/problem/P2508
视频直播讲解:
题目描述与示例
题目描述
存在一种虚拟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考虑以下特殊情况:
IPv4_lst长度不为4IPv4_lst中存在某一个字符串,不是纯数字IPv4_lst[0]即第一小节的取值范围不是1-128IPv4_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)为例,其过程如下:
- 以
#为分隔符,将原输入字符串分割为四个小节,为4个十进制数整数,即IPv4_lst = ["128", "0", "255", "255"]
IPv4_lst = input().split("#")
- 每个十进制整数都可以转换为一个两位的十六进制整数,即
["80", "00", "ff", "ff"]
- 十进制的
128、0、255、255分别对应十六进制的80、00、ff、ff - 之所以是两位的十六进制整数,是因为取值范围(
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))
- 将上述的
4个两位的十六进制整数进行拼接,得到一个八位的十六进制数"8000FFFF"
# 将4个十六进制数合并成一个长度为8的字符串
IPv4_str_16base = "".join(IPv4_lst_16base)
- 将这个八位的十六进制数转化为十进制整数,得到答案
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或了解更多

浙公网安备 33010602011771号