描述

输入描述:

输入

  1. 输入IP地址

  2. 输入10进制型的IP地址

输出描述:

输出

  1. 输出转换成10进制的IP地址

  2. 输出转换后的IP地址

示例

输入:
10.0.3.193
167969729
输出:
167773121
10.3.3.193

知识点:进制转换,字符串

难度:⭐⭐⭐


题解

方法一:直接十进制转换

图解

image-20211102163618251

算法流程

  • 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();
    }
}

复杂度分析

时间复杂度O(1)O(1),ip转成10进制数需要遍历4次,10进制数转成ip也需要遍历4次,总的时间复杂度为 O(1)

空间复杂度O(1)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);
    }
}

复杂度分析

时间复杂度O(1)O(1),ip转成10进制数需要遍历4次,10进制数转成ip也需要遍历4次,总的时间复杂度为 O(1)

空间复杂度O(1)O(1), 只需要常数级别的空间保存结果