标题:Java中,求两个数组的交集,使用了HashMap,排序
一、分析
- 方式一:长度较短的数组作为外层循环,使用两层for循环进行遍历
同时使用标记数组nums来判断此元素是否匹配成功了【匹配成功了,则将nums[j]=true】,最后通过return Arrays.copyOfRange(results, 0, t);
来返回数组
for(int i=0;i<numsMin.length;i++){
for(int j=0;j<numsMax.length;j++){
if(!nums[j] && (numsMin[i]==numsMax[j])){
nums[j]=true;
results[t++]=numsMin[i];
break;
}
}
}
- 方法二:首先将两个数组进行排序,使用两个“指针”【其实是两个下标i,j】进行移动,来判断是否到达了循环末尾
if(j>=numsMax.length) { break; }
注意两个数组相等的情况,所以加了此判断,让循环结束
while(i<numsMin.length) {
if(numsMin[i]==numsMax[j]) {
results[t++]=numsMin[i];
i++;
j++;
}else if(numsMin[i]>numsMax[j]) {
j++;
}else if(numsMin[i]<numsMax[j]){
i++;
}
//此时是两个数组长度相等时
if(j>=numsMax.length) {
break;
}
}
故可以直接如下,放在while一起判断了
while(i<numsMin.length && j<numsMax.length) {
if(numsMin[i]==numsMax[j]) {
results[t++]=numsMin[i];
i++;
j++;
}else if(numsMin[i]>numsMax[j]) {
j++;
}else if(numsMin[i]<numsMax[j]){
i++;
}
}
- 方法三:使用HashMap,相当于方法一的改进,使得两层for循环–>一层,大大提高了搜索速度
1、得到每一个nums1的键值对,放入map中,若有重复的,则覆盖,value【count++】
2、搜索,给一个key,找到对应的count,若count--后>0,则说明有多个该key被覆盖了,故重新设置value,map.put(num,count);
else说明该key没有被覆盖,故删去
//得到每一个nums1的键值对,放入map中,若有重复的,则覆盖,value【count++】
for(int num:nums1) {
int count=map.getOrDefault(num, 0)+1;
map.put(num,count);
}
int[] results=new int[nums1.length];
int index=0;
//搜索,给一个key,找到对应的count,若count--后>0,则说明有多个该key被覆盖了,故重新设置value,map.put(num,count);
// else说明该key没有被覆盖,故删去
for(int num:nums2) {
int count=map.getOrDefault(num, 0);
//map中,存在该key-value对
if(count>0) {
results[index++]=num;
//查看map,是否有多个该key被覆盖了,只需看--count>0?
count--;
//有多个该key被覆盖
if(count>0) {
map.put(num, count);
}else {
//无多个该key被覆盖
map.remove(num);
}
}
}
完整代码如下:
/**
* 测试求两个数组的交集
* @author dell
*
*/
public class TestArrayInterative {
/**
* 没用哈希表n^2
* 没用排序
* @param nums1
* @param nums2
* @return
*/
public int[] intersect(int[] nums1, int[] nums2) {
int[] numsMax=null;
int[] numsMin=null;
if(nums1.length>nums2.length) {
numsMax=nums1;
numsMin=nums2;
}else {
numsMax=nums2;
numsMin=nums1;
}
boolean[] nums=new boolean[numsMax.length];
int[] results=new int[numsMin.length];
int t=0;
//将boolean数组设置初始值为false
for(int i=0;i<nums.length;i++){
nums[i]=false;
}
for(int i=0;i<numsMin.length;i++){
for(int j=0;j<numsMax.length;j++){
if(!nums[j] && (numsMin[i]==numsMax[j])){
nums[j]=true;
results[t++]=numsMin[i];
break;
}
}
}
int[] results2=new int[t];
//精确数组results
for(int i=0;i<t;i++) {
results2[i]=results[i];
}
return results2;
}
@Test
public void test() {
int[] nums1=new int[] {4,9,5};
int[] nums2=new int[] {9,4,9,8,4};
// int[] nums1=new int[] {1,2,2,1};
// int[] nums2=new int[] {2,2};
int[] results = this.intersect(nums1,nums2);
for(int i:results) {
System.out.println(i);
}
}
/**
* 用排序
* @param nums1
* @param nums2
* @return
*/
public int[] intersect2(int[] nums1, int[] nums2) {
//按升序排序
Arrays.sort(nums1);
Arrays.sort(nums2);
int[] numsMax=null;
int[] numsMin=null;
if(nums1.length>nums2.length) {
numsMax=nums1;
numsMin=nums2;
}else {
numsMax=nums2;
numsMin=nums1;
}
int[] results=new int[numsMin.length];
int t=0;
int i=0;//最小值的索引
int j=0;//最大值的索引
while(i<numsMin.length) {
if(numsMin[i]==numsMax[j]) {
results[t++]=numsMin[i];
i++;
j++;
}else if(numsMin[i]>numsMax[j]) {
j++;
}else if(numsMin[i]<numsMax[j]){
i++;
}
//此时是两个数组长度相等时
if(j>=numsMax.length) {
break;
}
}
// int[] results2=new int[t];
// //精确数组results
//
// for(int ii=0;ii<t;ii++) {
// results2[ii]=results[ii];
// }
//
// return results2;
return Arrays.copyOfRange(results, 0, t);
}
@Test
public void test2() {
int[] nums1=new int[] {4,9,5};
int[] nums2=new int[] {9,4,9,8,4};
// int[] nums1=new int[] {1,2,2,1};
// int[] nums2=new int[] {2,2};
int[] results = this.intersect2(nums1,nums2);
for(int i:results) {
System.out.println(i);
}
}
/**
* 使用HashMap
* @param nums1
* @param nums2
* @return
*/
public int[] intersect3(int[] nums1, int[] nums2) {
//使得nums1最小,nums2最大
if (nums1.length > nums2.length) {
return intersect3(nums2, nums1);
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums1) {
int count = map.getOrDefault(num, 0) + 1;
map.put(num, count);
}
System.out.println("遍历map:");
Set<Entry<Integer,Integer>> set=map.entrySet();
for(Entry<Integer,Integer> entry:set) {
System.out.println(entry.getKey()+"-->"+entry.getValue());
}
System.out.println("输出结束;");
int[] intersection = new int[nums1.length];
int index = 0;
for (int num : nums2) {
int count = map.getOrDefault(num, 0);
if (count > 0) {
intersection[index++] = num;
count--;
if (count > 0) {
map.put(num, count);
} else {
map.remove(num);
}
}
}
return Arrays.copyOfRange(intersection, 0, index);
}
@Test
public void test3() {
// int[] nums1=new int[] {4,9,5};
// int[] nums2=new int[] {9,4,9,8,4};
int[] nums1=new int[] {1,2,2,1};
int[] nums2=new int[] {2,2};
int[] results = this.intersect3(nums1,nums2);
for(int i:results) {
System.out.println(i);
}
}
/**
* 使用HashMap
* @param nums1
* @param nums2
* @return
*/
public int[] intersect4(int[] nums1, int[] nums2) {
//使得nums1最小,nums2最大
if (nums1.length > nums2.length) {
return intersect4(nums2, nums1);
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//得到每一个nums1的键值对,放入map中,若有重复的,则覆盖,value【count++】
for(int num:nums1) {
int count=map.getOrDefault(num, 0)+1;
map.put(num,count);
}
int[] results=new int[nums1.length];
int index=0;
//搜索,给一个key,找到对应的count,若count--后>0,则说明有多个该key被覆盖了,故重新设置value,map.put(num,count);
// else说明该key没有被覆盖,故删去
for(int num:nums2) {
int count=map.getOrDefault(num, 0);
//map中,存在该key-value对
if(count>0) {
results[index++]=num;
//查看map,是否有多个该key被覆盖了,只需看--count>0?
count--;
//有多个该key被覆盖
if(count>0) {
map.put(num, count);
}else {
//无多个该key被覆盖
map.remove(num);
}
}
}
return Arrays.copyOf(results,index);
}
@Test
public void test4() {
int[] nums1=new int[] {4,9,5};
int[] nums2=new int[] {9,4,9,8,4};
// int[] nums1=new int[] {1,2,2,1};
// int[] nums2=new int[] {2,2};
int[] results = this.intersect4(nums1,nums2);
for(int i:results) {
System.out.println(i);
}
}
}