描述
输入描述:
输入
-
输入IP地址
-
输入10进制型的IP地址
输出描述:
输出
-
输出转换成10进制的IP地址
-
输出转换后的IP地址
示例
输入:
10.0.3.193
167969729
输出:
167773121
10.3.3.193
知识点:进制转换,字符串
难度:⭐⭐⭐
题解
方法一:直接十进制转换
图解:
算法流程:
- ip转成10进制数:
- 通过 ip 地址的 “.” 切分ip字符串为四个部分
- 从右往左对 ip 每一部分进行处理转换,每一部分相差2^8,因为每一部分最大值为255,二进制是8位
- 每一部分处理后的结果相加即可
- 10进制数转成ip:
- 从10进制的ip地址的右边一位开始转换
- 每次通过取模得到 ip 地址的其中8位,取余得到剩余的 24 位
- 每8位进行拼接字符串结果值
Java 版本代码如下:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
// ip
String ip = sc.nextLine();
// 十进制
long ipDeci = Long.parseLong(sc.nextLine());
System.out.println(transferToIpDecimal(ip));
System.out.println(transferToIpAddress(ipDeci));
}
}
// ip转成10进制数
public static long transferToIpDecimal(String ip) {
// 切分ip字符串
String[] ips = ip.split("\\.");
long res = 0;
// 从右往左对ip每一位进行转换
for (int i = ips.length - 1, n = 0; i >= 0; i--) {
// 如 10.0.3.193,每一位相差2^8
res += Integer.parseInt(ips[i]) * Math.pow(2, n);
n += 8;
}
return res;
}
// 10进制数转成ip
public static String transferToIpAddress(long ipDeci) {
StringBuilder sb = new StringBuilder();
long ipi = 0;
// 167969729
while (ipDeci > 0) {
// 从10进制的ip地址的右边8位开始转换
ipi = ipDeci % (long) Math.pow(2, 8);
// 剩余其他位
ipDeci = ipDeci / (long) Math.pow(2, 8);
if (sb.length() == 0) {
sb = sb.append(ipi);
} else {
// 头插法进行填充
sb = new StringBuilder().append(ipi).append(".").append(sb);
}
}
return sb.toString();
}
}
复杂度分析:
时间复杂度:,ip转成10进制数需要遍历4次,10进制数转成ip也需要遍历4次,总的时间复杂度为 O(1)
空间复杂度:, 只需要常数级别的空间保存结果
方法二:借助二进制转换
算法流程:
- ip转为十进制
- 借助工具类对每8位进行转换二进制,每8位作为一个十进制,转为二进制右边0补齐
- 二进制直接拼接字符串即可,每8位之间互相不影响,不存在进位,最后通过Long.parseLong 转为十进制
- 十进制转为ip地址
- 借助工具类转为二进制
- 遍历处理二进制的32位,在此之前不足32位则需要0右补齐, 因为还需要转为十进制
- 每次遍历8位的二进制,转为十进制,最后拼接为字符串
Java 版本代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String ipAddr = in.next();
long ipDeci = in.nextLong();
System.out.println(transferToIpDecimal(ipAddr));
System.out.println(transferToIpAddress(ipDeci));
}
}
// ip转为十进制
public static long transferToIpDecimal(String ipAddr) {
String[] split = ipAddr.split("\\.");
StringBuilder sb = new StringBuilder(32); // 用于存储32位二进制数
for (int i = 0; i < 4; i++) {
// 借助工具类进行转换位二进制
// 每8位作为一个十进制,转为二进制右边0补齐
// 二进制直接拼接字符串即可,每8位之间互相不影响,不存在进位
sb.append(String.format("%08d", Integer.parseInt(Integer.toBinaryString(Integer.parseInt(split[i])))));
}
// 二进制转十进制
return Long.parseLong(sb.toString(), 2);
}
// 十进制转为ip地址
public static String transferToIpAddress(long ipDeci) {
// 十进制转换为二进制
String ipBinary = Long.toBinaryString(ipDeci);
// 不足32位则需要0右补齐, 因为还需要转为十进制
if (ipBinary.length() < 32) {
StringBuilder ipBinaryFill = new StringBuilder(32);
for (int i = 1; i <= 32 - ipBinary.length(); i++) {
ipBinaryFill.append('0');
}
ipBinaryFill.append(ipBinary);
ipBinary = ipBinaryFill.toString();
}
StringBuilder ipAddr = new StringBuilder(16);
for (int i = 0; i < 32; i += 8) {
// 每8位的二进制转为十进制
ipAddr.append(Integer.parseInt(ipBinary.substring(i, i + 8), 2));
ipAddr.append(".");
}
// 最后的 "." 忽略
return ipAddr.substring(0, ipAddr.length() - 1);
}
}
复杂度分析:
时间复杂度:,ip转成10进制数需要遍历4次,10进制数转成ip也需要遍历4次,总的时间复杂度为 O(1)
空间复杂度:, 只需要常数级别的空间保存结果