package cccf;
import java.util.*;
import java.util.stream.Collectors;
/**
* 描述:代码注释以及格式化示例
* 创建人:@author Songguanye
* 创建时间:2019/3/28 9:42
* 修改理由:
* 修改内容:
*/
public class CIDRMerge {
private String ip;
private int len;
private String binaryIp;
private String getBinaryIp() {
return binaryIp;
}
private void setBinaryIp(String binaryIp) {
this.binaryIp=binaryIp;
}
private String getIp() {
return ip;
}
private void setIp(String ip) {
this.ip=ip;
}
private int getLen() {
return len;
}
private void setLen(int len) {
this.len=len;
}
private static List<CIDRMerge> handleIncompleteIpPrefix(String[] ipPrefixArray){
List<CIDRMerge> cIDRMergeList = new ArrayList<>();
for (String anIpPrefixArray : ipPrefixArray) {
CIDRMerge cidrMerge=new CIDRMerge();
StringBuilder binaryString=new StringBuilder();
if (anIpPrefixArray.contains("/")) {
//标准型或者省略后缀型
String[] tempArray=anIpPrefixArray.split("/");
String[] tempArray2=tempArray[0].split("\\.");
if (tempArray2.length - 1 == 2) {
cidrMerge.setIp(tempArray[0] + ".0");
} else if (tempArray2.length - 1 == 1) {
cidrMerge.setIp(tempArray[0] + ".0.0");
} else if (tempArray2.length - 1 == 0) {
cidrMerge.setIp(tempArray[0] + ".0.0.0");
} else if (tempArray2.length - 1 == 3) {
cidrMerge.setIp(tempArray[0]);
cidrMerge.setBinaryIp(binaryString.toString());
}
cidrMerge.setLen(Integer.parseInt(tempArray[1]));
} else {
//省略长度型
if (anIpPrefixArray.contains(".")) {
String[] tempArray=anIpPrefixArray.split("\\.");
if (tempArray.length - 1 == 2) {
cidrMerge.setIp(anIpPrefixArray + ".0");
cidrMerge.setLen(24);
} else if (tempArray.length - 1 == 1) {
cidrMerge.setIp(anIpPrefixArray + ".0.0");
cidrMerge.setLen(16);
} else if (tempArray.length - 1 == 0) {
cidrMerge.setLen(8);
cidrMerge.setBinaryIp(binaryString.toString());
} else if (tempArray.length - 1 == 3) {
cidrMerge.setIp(anIpPrefixArray);
cidrMerge.setLen(32);
cidrMerge.setBinaryIp(binaryString.toString());
}
} else {
cidrMerge.setIp(anIpPrefixArray + ".0.0.0");
cidrMerge.setLen(8);
}
}
String[] tt=cidrMerge.getIp().split("\\.");
for (String aTt : tt) {
String temp = String.format("%08d", Integer.valueOf(Integer.toBinaryString(Integer.parseInt(aTt))));
binaryString.append(temp);
}
cidrMerge.setBinaryIp(binaryString.toString());
cIDRMergeList.add(cidrMerge);
}
return cIDRMergeList;
}
/**
* 判断ip前缀是否合法
* @param binaryIp 二进制ip前缀
* @return 是否合法
*/
private static Boolean isLegal(String binaryIp,int len){
if(len > 32){
return false;
}
StringBuilder zeroString = new StringBuilder();
for (int i=0; i < 32 - len; i++) {
zeroString.append("0");
}
return binaryIp.substring(len, binaryIp.length()).equals(zeroString.toString());
}
/**
* 根据ip地址为第一关键字 前缀长度为第二关键字进行前缀列表的排序
* @param cIDRMergeList 前缀列表
* @return 排序后的前缀列表
*/
private static List<CIDRMerge> cIDRMergeListSort(List<CIDRMerge> cIDRMergeList){
List<CIDRMerge> cIDRMergeListSortByIp = cIDRMergeList.stream().sorted(Comparator.comparing(CIDRMerge::getBinaryIp)).collect(Collectors.toList());
for (int i=0; i < cIDRMergeListSortByIp.size()-1; i++) {
if(cIDRMergeListSortByIp.get(i).getIp().equals(cIDRMergeListSortByIp.get(i+1).getIp()) && cIDRMergeListSortByIp.get(i).getLen() > cIDRMergeListSortByIp.get(i+1).getLen()){
int l = cIDRMergeListSortByIp.get(i).getLen();
cIDRMergeListSortByIp.get(i).setLen(cIDRMergeListSortByIp.get(i+1).getLen());
cIDRMergeListSortByIp.get(i+1).setLen(l);
}
}
return cIDRMergeListSortByIp;
}
/**
* 判断b的匹配集是否是a的匹配集的子集
* @param a ip前缀(列表)
* @param b ip前缀(列表)
* @return 匹配集
*/
private static Boolean isSubList(CIDRMerge a,CIDRMerge b){
if(a.getIp().equals("0.0.0.0") && a.getLen()==0) {
return true;
}
return b.len >= a.len && b.getBinaryIp().substring(0, a.len).equals(a.getBinaryIp().substring(0, a.len));
}
/**
* 判断a和b的匹配集是否等于a1的匹配集
* @param a
* @param b
* @return
*/
private static Boolean isUnion(CIDRMerge a,CIDRMerge b){
if(a.len == b.len){
int a1 = a.len - 1;
//判断a.ip+"/"+a1是否合法
if (isLegal(a.getBinaryIp(),a1)) {
//a1的匹配集范围
return a.getBinaryIp().substring(0,a1).equals(b.getBinaryIp().substring(0,a1));
}
}
return false;
}
/**
* 从小到大合并前缀列表
* @param cIDRMergeList 前缀列表
* @return 合并后的前缀列表
*/
private static void mergeCIDRMergeListFromMinToMax(List<CIDRMerge> cIDRMergeList){
for (int i=0; i < cIDRMergeList.size()-1; i++) {
for (int j=i+1;j < cIDRMergeList.size();j++){
if(CIDRMerge.isSubList(cIDRMergeList.get(i),cIDRMergeList.get(j))){
cIDRMergeList.remove(cIDRMergeList.get(j));
--j;
}
}
}
}
/**
* 同级合并前缀列表
* @param cIDRMergeList 前缀列表
* @return 合并后的前缀列表
*/
private static void mergeCIDRMergeListSameLevel(List<CIDRMerge> cIDRMergeList){
for (int j=0; j < cIDRMergeList.size(); j++) {
if(j+1 < cIDRMergeList.size() && CIDRMerge.isUnion(cIDRMergeList.get(j),cIDRMergeList.get(j+1))){
cIDRMergeList.get(j).setLen(cIDRMergeList.get(j).getLen()-1);
cIDRMergeList.remove(cIDRMergeList.get(j+1));
if(j != 0){
j -= 2;
}
}
}
}
public static void main (String[] args){
List<CIDRMerge> cIDRMergeList;
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
String[] ips = new String[n];
for (int i=0; i < n; i++) {
ips[i] = scanner.nextLine();
}
//处理读取的ip前缀数组,返回前缀列表
cIDRMergeList = CIDRMerge.handleIncompleteIpPrefix(ips);
//前缀列表排序
List<CIDRMerge> cIDRMergeListSort = CIDRMerge.cIDRMergeListSort(cIDRMergeList);
//从小到大合并前缀列表
CIDRMerge.mergeCIDRMergeListFromMinToMax(cIDRMergeListSort);
//同级合并
CIDRMerge.mergeCIDRMergeListSameLevel(cIDRMergeListSort);
if (cIDRMergeListSort != null && cIDRMergeListSort.size() > 0) {
cIDRMergeListSort.forEach(cIDRMerge -> System.out.println(cIDRMerge.ip + "/" + cIDRMerge.len));
}
}
}
总结:运行超时导致只得80分,有时间优化一下,逻辑已经没有问题的,只是性能不满足。
本文介绍了一种用于合并CIDR(无类别域间路由)格式IP地址前缀的算法。该算法能够处理不完整或格式不一的IP前缀,并通过排序、从小到大合并以及同级合并等步骤实现有效合并。
4298

被折叠的 条评论
为什么被折叠?



