[答对:高分]求一个简单的算法。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

javasishen 2011-08-24 10:19:41
场景:有5对IP地址,要求计算出这5对IP地址是否有交集。(2对IP地址是否有交集已经知道了,关键是5对IP地址怎么比较,效率最高)
...全文
449 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
hq333 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 tjcyjd 的回复:]
我擦啊,这个问题也问,你直接转换为long类型比较大小不就行了么,11111-66666和22222-99999有没有交集,你说吧,道理是一模一样的啊,这个问题,我晕,给我分。
[/Quote]
9楼的代码,就是转换为long类型的,不算繁复,也不算简单。似乎仁兄觉得此题是小菜一碟,有什么简单快捷的方法,不妨晒晒。只要是好主意,不用以红色抢眼,也会有很多人赞赏的。
hq333 2011-08-30
  • 打赏
  • 举报
回复
可找出哪两组有交集,并列出重复的IP:
import java.util.*;
public class Test_CompareIP2{
public static void main(String[] args){
// String str="192.168.1.3-192.168.1.5 192.168.1.2-192.168.1.6 192.168.1.5-192.168.1.10";
String str="192.168.1.1-192.168.1.5 192.168.1.2-192.168.1.4 192.168.1.3-192.168.1.10";
// String str="192.168.1.3-192.168.1.5 192.168.1.1-192.168.1.2 192.168.1.5-192.168.1.10";
//将IP地址不够3位的段,用0补够3位
str=str.replaceAll("(\\d+)","00$1"); //每段加两个0
str=str.replaceAll("0*(\\d{3})","$1"); //每段只保留三位,前面的0去掉
String[] arr,arr1;
arr=str.split(" +");
arr1=str.split(" +");
Arrays.sort(arr1);
List<String> ls=new ArrayList<String>();
for(String a:arr1){
String[] temp=a.split("-");
ls.add(temp[0]);
ls.add(temp[1]);
}
int m=0,n=0;
String message="";
for(int i=1;i<ls.size()-2;i=i+2){
if(ls.get(i).compareTo(ls.get(i+1))<0) continue;
else{
String[] arr2={ls.get(i),ls.get(i+1),ls.get(i+2)};
Arrays.sort(arr2);
//查找IP在哪组
for(int j=0;j<arr.length;j++){
if(arr[j].equals(ls.get(i-1)+"-"+ls.get(i))) m=j+1;
if(arr[j].equals(ls.get(i+1)+"-"+ls.get(i+2))) n=j+1;
}
message=arr2[0]+"-"+arr2[1];
message=message.replaceAll("0*(\\d+)","$1"); //去掉IP多余的0
System.out.printf("第%d组与第%d组有交集:\n%s\n",m,n,message);
}
}
if(message=="")
System.out.println("没有交集");
}
}
小赖赖 2011-08-30
  • 打赏
  • 举报
回复
其实还有个办法,就是利用数据库
假设有表结构如下:
TABLE_IPS
min_ip max_ip
自关联
select P1.*,P2.* from TABLE_IPS P1 inner join TABLE_IPS P2
on (P1.min_ip>=P2.min_ip and P1.min_ip<=P2.max_ip)
or (P1.max_ip>=P2.min_ip and P1.max_ip<=P2.max_ip)
这样把存在交集的IP对可以全部找到
m安然 2011-08-30
  • 打赏
  • 举报
回复
	public static void main(String[] argv) throws Exception {
List<String> list = new ArrayList<String>();
list.add("192.168.1.3-192.168.1.5");
list.add("192.168.1.1-192.168.1.2");
list.add("192.168.1.1-192.168.1.3");
for (int i = 0; i < list.size() - 1; i++) {
for (int j = i + 1; j < list.size(); j++) {
String ips1 = list.get(i);
String ips2 = list.get(j);
boolean result = compareIps(ips1, ips2);
if (result) {
System.out.println(ips1 + " 和 " + ips2 + " 有交集");
} else {
System.out.println(ips1 + " 和 " + ips2 + " 没有交集");
}
}
}
}

// 比较两组ip是否有交集
private static boolean compareIps(String ips1, String ips2) {
String[] array1 = ips1.split("-");
String[] array2 = ips2.split("-");
if (compareIp(array1[0], array2[0]) >= 0 && compareIp(array1[0], array2[1]) <= 0) {
return true;
} else if (compareIp(array1[1], array2[0]) >= 0 && compareIp(array1[1], array2[1]) <= 0) {
return true;
}
return false;
}

// 比较两个ip , 如果前者比后者大 , 则返回正数
private static int compareIp(String ip1, String ip2) {
String[] array1 = ip1.split("\\.");
String[] array2 = ip2.split("\\.");
for (int i = 0; i < 4; i++) {
int i1 = Integer.parseInt(array1[i]);
int i2 = Integer.parseInt(array2[i]);
if (i1 > i2) {
return 1;
} else if (i1 < i2) {
return -1;
}
}
return 0;
}
Java高知社区 2011-08-30
  • 打赏
  • 举报
回复
我擦啊,这个问题也问,你直接转换为long类型比较大小不就行了么,11111-66666和22222-99999有没有交集,你说吧,道理是一模一样的啊,这个问题,我晕,给我分。
jsudavid 2011-08-30
  • 打赏
  • 举报
回复
我也有一点点思路,等想好了再贴上来
hq333 2011-08-30
  • 打赏
  • 举报
回复
  其实,我的思路与LS的差不多,只是没想到“2次排序结果不同,则肯定有交集”。判断相邻的2对IP是否有交集,也用不着retainAll的。LS的回复,激发我详细写写思路,反正也睡不着。
  这题可以用倒推法。假设已有5对IP是无交集的,那么会是下面的状况:

A1┗━━┛A2 B1┗━━┛B2 C1┗━━┛C2 D1┗━━┛D2 E1┗━━┛E2

并且A1<A2<B1<B2<C1<C2<D1<D2<E1<E2,相邻的IP,A2=B1也不可能,如等则会有一IP重复。
  先将IP不分头尾,取出排序(TreeSet是有序集合,省了排序一步);再将IP按组排序,若无交集,此IP序列应与前面序列相同。如出现“A2=B1”,TreeSet比List少一元素,不等;但“B2=B1”而无交集呢?TreeSet也会少一元素。刚开始没考虑这一情况,后来:开始、结束地址等就只加一个入List,避开了这种情况。
以下代码,只是判断有无交集,没对交集处理,欢迎测试:
import java.util.*;
public class Test_CompareIP1{
public static void main(String[] args){
// String str="192.168.1.3-192.168.1.5 192.168.1.2-192.168.1.6 192.168.1.5-192.168.1.10";
// String str="192.168.1.3-192.168.1.5 192.168.1.2-192.168.1.2 192.168.1.6-192.168.1.10";
String str="192.168.1.3-192.168.1.5 192.168.1.1-192.168.1.2 192.168.1.5-192.168.1.10";
//将IP地址不够3位的段,用0补够3位
str=str.replaceAll("(\\d+)","00$1"); //每段加两个0
str=str.replaceAll("0*(\\d{3})","$1"); //每段只保留三位,前面的0去掉

String[] arr=str.split(" +|-"); //空格或-,split
Set<String> ts=new TreeSet<String>();
for(String a:arr)
ts.add(a);

arr=str.split(" +");
Arrays.sort(arr);
List<String> ls=new ArrayList<String>();
for(String a:arr){
String[] temp=a.split("-");
ls.add(temp[0]);
if (!temp[0].equals(temp[1])) //开始、结束地址等就只加一个,是为了与ts比较
ls.add(temp[1]);
}
if(ls.toString().equals(ts.toString()))
System.out.println("没有交集");
else
System.out.println("有交集");
}
}

ps:对交集处理的,列出重复IP、调整范围使其不重复等等,留待下回分解。
TKD03072010 2011-08-29
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 qybao 的回复:]

把ip地址转为long,然后用集合的交集运算就可以了
Java code
import java.util.*;

public class Test {
public static void main(String[] args) throws Throwable {
String[] ipGroup = {"192.168.1.3-192.168.1.5", "1……
[/Quote]
顶一下
安心逍遥 2011-08-29
  • 打赏
  • 举报
回复
a.b.c.d -> a*1000000000+b*1000000+c*1000+d将ip地址转成long类型处理,然后就不用我说了吧,几个数字判断是否有交集


小赖赖 2011-08-29
  • 打赏
  • 举报
回复
因为2对IP地址是否有交集已经知道了
只需要考虑如何比较5对IP地址效率高
可以用2次排序解决
假设5对IP为,左边的IP总是比右边的小
A1->A2 B1->B2 C1->C2 D1->D2 E1->E2
根据A1,B1,C1,D1,E1的值排序
再对A2,B2,C2,D2,E2排序
如果2次排序结果一样,
假设顺序是EDCBA
只要判断相邻的2对IP是否有交集既可
如果2次排序结果不同,则肯定有交集
hq333 2011-08-29
  • 打赏
  • 举报
回复
这题要先设定子网掩码是一样的。
  一般的想法是,每对IP地址,生成其全部IP,再判断它们是否有交集,刚巧java的set、list都有retainAll来判断交集。用hashSet可能效率更好,不断add,最后判断一下size,如size比原来的少,说明有重复,有交集了。
  不过,这显然不是高效的算法,特别是IP多的时候,要不LZ也不来高分求解了。平常我们判断时,是看看IP地址是否包含了,结束地址是否比另一对开始地址大,等等。按照这思路,我考虑过将开始地址、结束地址分别保存在一数组,再通过对两数组作比较、处理,来判断交集。可惜,试了几次,此路不通,因IP的范围是未知的。
  只能两两判断了?后来,发现只要将最小的开始地址对应的结束地址,如"192.168.1.3-192.168.1.5 192.168.1.2-192.168.1.6 192.168.1.5-192.168.1.10"是192.168.1.6,与第二小的开始地址--192.168.1.3作比较,>=则有交集;其它就将该组地址移出,再找--最小的开始地址对应的结束地址,与第二小的开始地址作比较,如此循环。
小绵羊 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 qybao 的回复:]

把ip地址转为long,然后用集合的交集运算就可以了
Java code
import java.util.*;

public class Test {
public static void main(String[] args) throws Throwable {
String[] ipGroup = {"192.168.1.3-192.168.1.5", "1……
[/Quote]
阿宝
qybao 2011-08-24
  • 打赏
  • 举报
回复
把ip地址转为long,然后用集合的交集运算就可以了
import java.util.*;

public class Test {
public static void main(String[] args) throws Throwable {
String[] ipGroup = {"192.168.1.3-192.168.1.5", "192.168.1.2-192.168.1.6", "192.168.1.5-192.168.1.10"};
List<List<Long>> list = new ArrayList<List<Long>>();
long[] num = {0, 0};
for (int i=0, j=0; i<ipGroup.length; i++) { //把ip地址转为long并保存到集合中
for (String ip : ipGroup[i].split("-")) {
num[j%2] = 0;
for (String n : ip.split("[.]")) {
num[j%2] = num[j%2]*1000 + Long.valueOf(n);
}
j++;
}
List<Long> l = new ArrayList<Long>();
for (long k=num[0]; k<=num[1]; k++) { //从ip地址开始到结束保存到集合
l.add(k);
}
list.add(l);
}

for (int i=0; i<list.size(); i++) { //循环取集合
for (int j=i+1; j<list.size(); j++) { //和自己以外的其他集合做交集运算
List<Long> l = new LinkedList<Long>(list.get(i));
l.retainAll(list.get(j)); //取交集
if (l.size() > 0) { //如果有交集则打印
System.out.printf("gip[%d] n gip[%d] = {", i+1, j+1);
for (int k=0; k<l.size(); k++) {
long t = l.get(k);
System.out.printf("%d.%d.%d.%d, ", t/1000000000, (t/1000000)%1000, (t/1000)%1000, t%1000);
}
System.out.printf("}\n");
}
}
}
}
}
小笨熊 2011-08-24
  • 打赏
  • 举报
回复
就是一个交集哇,搞什么算法,太麻烦。你可以截取IP的最后字段,拿出来比较下
尘缘udbwcso 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 grubby4k 的回复:]
引用 2 楼 x19881216 的回复:

a.b.c.d -> a*1000000000+b*1000000+c*1000+d将ip地址转成long类型处理,然后就不用我说了吧,几个数字判断是否有交集


我感觉用二叉树遍历及生成,解决该问题比较好。
具体方案如下:
A.B.C.D A-作为树的根节点,B\C\D依次按照由小到大的顺序前序生成,然后后四对IP进行插入该树的操作。
……
[/Quote]

这个弄的有点复杂了吧
grubby4k 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 x19881216 的回复:]

a.b.c.d -> a*1000000000+b*1000000+c*1000+d将ip地址转成long类型处理,然后就不用我说了吧,几个数字判断是否有交集
[/Quote]

我感觉用二叉树遍历及生成,解决该问题比较好。
具体方案如下:
A.B.C.D A-作为树的根节点,B\C\D依次按照由小到大的顺序前序生成,然后后四对IP进行插入该树的操作。
如果A就不一样,就说明是2棵不同的树 无交集
softroad 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 x19881216 的回复:]

a.b.c.d -> a*1000000000+b*1000000+c*1000+d将ip地址转成long类型处理,然后就不用我说了吧,几个数字判断是否有交集
[/Quote]

这个方法不错。
javasishen 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chdw 的回复:]

不明白什么叫 5对ip, 是指5组,每组2个ip吗? 什么叫有交集?相同?
[/Quote]
是5指5组IP地址,比如:192.168.1.3-192.168.1.5和192.168.1.2-192.168.1.6就是交集
ChDw 2011-08-24
  • 打赏
  • 举报
回复
不明白什么叫 5对ip, 是指5组,每组2个ip吗? 什么叫有交集?相同?
小绵羊 2011-08-24
  • 打赏
  • 举报
回复
a.b.c.d -> a*1000000000+b*1000000+c*1000+d将ip地址转成long类型处理,然后就不用我说了吧,几个数字判断是否有交集
加载更多回复(3)

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧