当前位置:首页 > 技术 > 正文内容

IPv4地址区间合并算法实现

访客 技术 2026年6月6日 1

IPv4地址区间合并方案

问题定义

输入包含多个IPv4地址表示项,支持单个IP地址或IP地址段形式。需将输入数据进行去重合并,输出连续的地址区间。

输入示例

{"192.168.0.1", "192.168.0.12-192.168.0.15", "192.168.0.2", 
 "192.168.0.7-192.168.0.9", "192.168.0.11", "192.168.0.3-192.168.0.5",
 "192.168.0.16", "192.168.0.100"}

输出示例

{"192.168.0.1-192.168.0.5", "192.168.0.7-192.168.0.9", 
 "192.168.0.11-192.168.0.16", "192.168.0.100"}

该问题基于经典区间合并算法,但需处理IP地址的特殊性。由于Java的int类型无法完整表示32位IP地址,需使用long类型进行存储和比较。转换过程涉及字符串与二进制位操作的双向映射。

地址编码转换

将IP地址转换为long类型的核心思想是:将四个8位字段通过位移和按位或操作组合成32位二进制数。以下为三种实现方式:

位移优先方案

public static long parseIpToLong(String ip) {
    String[] segments = ip.split("\\.");
    long value = 0;
    
    for (int i = 0; i < 4; i++) {
        value |= Long.parseLong(segments[i]) << (24 - 8 * i);
    }
    
    return value;
}

循环优化方案

public static long parseIpToLong(String ip) {
    String[] segments = ip.split("\\.");
    long value = 0;
    
    for (int i = 0; i < 4; i++) {
        value |= Long.parseLong(segments[i]) << (24 - 8 * i);
    }
    
    return value;
}

位掩码方案

public static String formatIpAddress(long ip) {
    StringBuilder sb = new StringBuilder();
    
    sb.append((ip >> 24) & 0xFF).append(".");
    sb.append((ip >> 16) & 0xFF).append(".");
    sb.append((ip >> 8) & 0xFF).append(".");
    sb.append(ip & 0xFF);
    
    return sb.toString();
}

区间合并算法

实现核心逻辑如下:

  1. 将地址转换为数值数组
  2. 按起始地址排序
  3. 遍历数组进行合并
public static long[][] combineIntervals(long[][] intervals) {
    Arrays.sort(intervals, Comparator.comparingLong(a -> a[0]));
    
    List<long[]> result = new ArrayList<>();
    long start = intervals[0][0], end = intervals[0][1];
    
    for (int i = 1; i < intervals.length; i++) {
        if (intervals[i][0] <= end + 1) {
            end = Math.max(end, intervals[i][1]);
        } else {
            result.add(new long[]{start, end});
            start = intervals[i][0];
            end = intervals[i][1];
        }
    }
    result.add(new long[]{start, end});
    
    return result.toArray(new long[result.size()][2]);
}

完整实现

import java.util.*;

public class AddressMerger {
    public static void main(String[] args) {
        String[] entries = {"192.168.0.1", "192.168.0.12-192.168.0.15", 
                           "192.168.0.2", "192.168.0.7-192.168.0.9", 
                           "192.168.0.11", "192.168.0.3-192.168.0.5", 
                           "192.168.0.16", "192.168.0.100"};
        
        List<String> output = processAddresses(entries);
        
        for (String addr : output) {
            System.out.println(addr);
        }
    }

    public static List<String> processAddresses(String[] input) {
        List<String> result = new ArrayList<>();
        long[][] intervals = new long[input.length][2];
        
        for (int i = 0; i < input.length; i++) {
            String entry = input[i];
            int dashIndex = entry.indexOf('-');
            
            if (dashIndex > 0) {
                intervals[i][0] = parseIpToLong(entry.substring(0, dashIndex));
                intervals[i][1] = parseIpToLong(entry.substring(dashIndex + 1));
            } else {
                intervals[i][0] = parseIpToLong(entry);
                intervals[i][1] = intervals[i][0];
            }
        }
        
        intervals = combineIntervals(intervals);
        
        for (long[] interval : intervals) {
            if (interval[0] == interval[1]) {
                result.add(formatIpAddress(interval[0]));
            } else {
                result.add(formatIpAddress(interval[0]) + "-" + formatIpAddress(interval[1]));
            }
        }
        
        return result;
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。