两个数组取交集的算法

在Lucene中,如果用户的查询向量Term t = {xx,xx,……},BooleanQuery为AND时,每个t---->对应得到的倒排列表,倒排列表由许多的倒排索引项构成,然后取其中重复的文档编号,然后进行排序。器核心思想类似于如下问题:

现有两个数组:int []data1 = {12,45,65,2,5} int []data2 = {12,5,-8,9},取其中的交集。

实现的方案有很多,现在采取一种时间和空间相对较好的算法:集合压缩算法,即:1.分别计算两个数组的min和max(取值范围),加入到rangeList 中,然后计算rangeLis中重复的数值,加入到result(list)中;

2.计算rangeList的取值范围交集,比如[1,20,3,15],两个数组的取值范围交集为[3,15],放在数组中,然后根据这个交集分别去除两个数组中不在此范围内的数值,清空rangeList,清零数组;

3.重复上述步骤,直到符合终止条件位置。

以上是逻辑实现,最重要的还是数据结果,由于在这个过程中,会不断地去除数组中的数值,所以底层采用链式存储的线性表,性能会比较高。

今天下午试着写了这个算法,经过调试后,准确无误,现在上传代码,以供分享:

package com.txq.dataStructure;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;

/**
* 对两个数组取交集
* @author TongXueQiang
* @date 2016/05/12
*/

public class DataIntersection {
// 存储原始数据的链表
private Queue<Integer> data1 = new ConcurrentLinkedDeque<Integer>();
private Queue<Integer> data2 = new ConcurrentLinkedDeque<Integer>();
// 存放两个数据集取值范围的集合
private List<Integer> minAndMax = new ArrayList<Integer>();
// 存放两个取值范围的交集
private int[] intersection = new int[2];
// 存储两个数据集交集的结果集
private List<Integer> result = new ArrayList<Integer>();

public List<Integer> intersection(int[] originalData, int[] originalData1) {
// 1.数据备份
for (int i : originalData) {
data1.add(i);
}
for (int j : originalData1) {
data2.add(j);
}
while (true) {
// 2.计算两个集合的取值范围,加到minAndMax中
minAndMax.add(Collections.min(data1));
minAndMax.add(Collections.max(data1));
minAndMax.add(Collections.min(data2));
minAndMax.add(Collections.max(data2));
// 3.计算minAndMax中相同的数值,加入到result中,然后分别去除两个数据集中的这个相同的数值
int intersect;
int sum1 = sum(minAndMax);
Set<Integer> set = new HashSet<Integer>(minAndMax);
int sum2 = sum(set);
if (set.size() == 1) {// 如果set的size==1,直接输出结果
for (int i : set)
result.add(i);
return result;
} else if (minAndMax.size() - set.size() == 1) {
intersect = sum1 - sum2;
// 加入到result中
result.add(intersect);
// 对data1和data2分别去除intersection
data1.remove(intersect);
data2.remove(intersect);
} else if (set.size() == 2) {// set本身就是intersection
if (minAndMax.get(0) == minAndMax.get(1) && minAndMax.get(2) == minAndMax.get(3)) {
return null;
} else if (minAndMax.get(0) != minAndMax.get(1) && minAndMax.get(2) != minAndMax.get(3)) {
// 加入到result中
result.addAll(set);
// 对data1和data2分别去除intersection
for (int num : set) {
data1.remove(num);
data2.remove(num);
}
} else if (minAndMax.get(0) != minAndMax.get(1) || minAndMax.get(2) != minAndMax.get(3)) {
if (minAndMax.get(0) != minAndMax.get(1)) {
intersect = minAndMax.get(2);
// 加入到result中
result.add(intersect);
// 对data1和data2分别去除intersection
data1.remove(intersect);
data2.remove(intersect);
}
if (minAndMax.get(2) != minAndMax.get(3)) {
intersect = minAndMax.get(0);
// 加入到result中
result.add(intersect);
// 对data1和data2分别去除intersection
data1.remove(intersect);
data2.remove(intersect);
}
}

}

// 4.计算两个取值范围的交集,放入intersection数组中
intersection[0] = Math.max(minAndMax.get(0), minAndMax.get(2));
intersection[1] = Math.min(minAndMax.get(1), minAndMax.get(3));

// 5.分别去除不在intersection范围内的数值
removeNotInIntersection(data1);
removeNotInIntersection(data2);
// 终止条件
if (intersection[0] > intersection[1] || data1.size() == 0 || data2.size() == 0) {
break;
}
// 6.清空minAndMax,清零intersection
minAndMax.clear();
intersection = setIntersectToZero(intersection);
}
return result;

}

private int[] setIntersectToZero(int[] intersection) {
for (int i = 0; i < intersection.length; i++) {
intersection[i] = 0;
}
return intersection;
}

/**
* 分别去除不在intersection范围内的数值
*
* @param data
*/
private void removeNotInIntersection(Queue<Integer> data) {
if (data.size() == 0) {
return;
}
int min = Collections.min(data);
int max = Collections.max(data);
while (max > intersection[1] || min < intersection[0]) {
if (max > intersection[1])
data.remove(max);
if (min < intersection[0])
data.remove(min);
if (data.size() == 0) {
break;
}
min = Collections.min(data);
max = Collections.max(data);
}
}

/**
* 求和
*
* @param collection
* @return
*/
private Integer sum(Collection<Integer> collection) {
int sum = 0;
for (int i : collection) {
sum += i;
}
return sum;
}
}

时间: 2024-11-10 13:25:34

两个数组取交集的算法的相关文章

数组去重和两个数组求交集

引言 今天在项目中一个功能要用到两个数组求交集的算法. 大概是这样: 两个表格分别用easyui datagrid实现,要把A表格的一列数据和B表格的一列数据取出来,然后去重,去重后求交集. 那么在计算出的交集中分别根据求出的数据选中两个表格的对应行. 故用到js数组去重和求交集. 交集 Array.prototype.intersect = function(b) { var flip = {}; var res = []; for(var i=0; i< b.length; i++) fli

前端与算法 leetcode 350. 两个数组的交集 II

目录 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 概要 提示 解析 解法一:哈希表 解法二:双指针 解法三:暴力法 算法 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出: [4,9] 说明

求两个数组的交集

问题: 给你两个排序的数组,求两个数组的交集. 比如: A = 1 3 4 5 7, B = 2 3 5 8 9, 那么交集就是 3 5. 思路: 1. 每一次从B数组中取一值,然后在A数组里逐个比较,如果有相等的,则保存.该算法复杂度为 O(MN). M, N 分别为数组 A B 的长度. 2. 因为A B 都排过序,所以,每一次从B数组取值后,可以利用二分查找看是否在数组A里有B所对应的值,这样复杂度变成了O(N lg M). 这里,如果N 比 M 大,可以从A中取值,然后在B中判断是否有A

【Leetcode】【简单】【350. 两个数组的交集 II】【JavaScript】

题目描述 350. 两个数组的交集 II 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2]输出: [2,2] 示例 2: 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]输出: [4,9] 说明: 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致.我们可以不考虑输出结果的顺序. 进阶: 如果给定的数组已经排好序呢?你将如何优化你的算法?如果 nums1 的大小比 nu

Leecode刷题之旅-C语言/python-349两个数组的交集

/* * @lc app=leetcode.cn id=349 lang=c * * [349] 两个数组的交集 * * https://leetcode-cn.com/problems/intersection-of-two-arrays/description/ * * algorithms * Easy (60.49%) * Total Accepted: 15.1K * Total Submissions: 25K * Testcase Example: '[1,2,2,1]\n[2,2

三种方法求解两个数组的交集

package com.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; //求两个数组的交集 public class FindIntersectionBetweenTwoArrays { //算法一:暴力搜索,时间复杂度O(n^2),空间复杂度O(1) public ArrayList

JS - 计算两个数组的交集、差集、并集、补集(多种实现方式)

方法一:最普遍的做法 使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本.也不用引入其他第三方库. 1,直接使用 filter.concat 来计算 var a = [1,2,3,4,5] var b = [2,4,6,8,10] //交集 var c = a.filter(function(v){ return b.indexOf(v) > -1 }) //差集 var d = a.filter(function(v){ return b.index

js取两个数组的交集|差集|并集|补集|去重示例代码

http://www.jb51.net/article/40385.htm 代码如下: /** * each是一个集合迭代函数,它接受一个函数作为参数和一组可选的参数 * 这个迭代函数依次将集合的每一个元素和可选参数用函数进行计算,并将计算得的结果集返回 {%example <script> var a = [1,2,3,4].each(function(x){return x > 2 ? x : null}); var b = [1,2,3,4].each(function(x){re

两个数组的交集 II [ LeetCode - 350 ]

原题地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/description/ 给定两个数组,写一个方法来计算它们的交集. 例如: 给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2]. 注意: 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致. 我们可以不考虑输出结果的顺序. 跟进: 如果给定的数组已经排好序呢?你将如何优化你的算法? 如果 nums