查找三个阵列中至少两个中存在的数字

时间:2014-03-06 20:32:45

标签: java arrays algorithm

我如何解决以下问题:

  

创建一个包含在至少两个给定数组中的整数数组。

例如:

int[] a1 = new int[] { 1, 2, 3, 4, 5 };          
int[] a2 = new int[] { 5, 10, 11, 8 };           
int[] a3 = new int[] { 1, 7, 6, 4, 5, 3, 11 };

必须提供结果数组

int[] result = new int[] {1, 3, 4, 5, 11}

P.S。我对如何处理这个问题的建议感兴趣(“算法”),而不是Java utils给我的答案

12 个答案:

答案 0 :(得分:3)

  1. a1个号码放在Map<Integer,Integer> count中,使用值作为键,并将计数设置为1
  2. a2个数字放入同一张地图中。如果项目不存在,请指定1的计数,否则为其分配现有计数+ 1
  3. a3个数字放入同一张地图中。如果项目不存在,请指定1的计数,否则为其分配现有计数+ 1
  4. 浏览地图中的条目,并输出值大于1的所有键。
  5. 该算法在三个数组中的元素组合数量中分摊线性时间。

    如果三个数组中的数字限制为1000或其他相对较小的数字,则可以完全避免使用集合,但根据数字的上限使用可能更昂贵的算法:替换地图使用数组counts[MAX_NUM+1],然后运行相同的算法,如下所示:

    int[] counts = new int[MAX_NUM+1];
    for (int a : a1) counts[a]++;
    for (int a : a2) counts[a]++;
    for (int a : a3) counts[a]++;
    for (int i = 0 ; i != MAX_NUM+1 ; i++) {
        if (counts[i] > 1) {
            System.out.println(i);
        }
    }
    

答案 1 :(得分:3)

您可以将3个数组视为sets,并查找某些对的intersection中的每个元素。

基本上,您正在寻找(set1 [intersection] set2) [union] (set2 [intersection] set3) [union] (set1 [intersection] set2)

我同意它可能不是最简单的方式来实现您的目标,但能够将一个问题减少到另一个是每个程序员都应该掌握的技巧,这个解决方案应该非常教育

答案 2 :(得分:0)

在没有集合的情况下执行此操作的唯一方法是从数组中获取元素,迭代剩余的两个数组以查看是否找到重复项(然后中断并移动到下一个元素)。您需要对三个阵列中的两个阵列执行此操作,因为当您转到第三个阵列时,您已经有了答案。

答案 3 :(得分:0)

我喜欢画维恩图。你知道那个带有三个相交圆的图,例如见here

然后您会看到补码更容易描述: 那些只存在于一个数组中的元素并不有趣。

所以你可以在一个哈希映射中建立一个频率列表(即key = element,value =你在多少数组中找到它[第一次]的数量),然后在最后一个传递中选择所有出现的元素不止一次。

为简单起见,我使用了套装。如果数组包含多个具有相同值的条目,则在构建频率列表时必须忽略这些额外的出现。

答案 4 :(得分:0)

数学上可以解决这个问题:

您可以使用三个阵列中的每个阵列构建三个集合,因此每个阵列中的重复条目只会在每个集合中出现一次。然后,至少在三组中的两组中出现的条目是解决方案。

给出了它们
(S_1 intersect S_2) union (S_2 intersect S_3) union (S_3 intersect S_1)

答案 5 :(得分:0)

考虑问题以及您可能使用的不同策略:

  1. 浏览每个数组中的每个条目,如果该条目尚未包含在&#34;重复项中#34;结果,然后查看该条目是否在每个剩余的数组中。如果是,则添加到重复项并返回到下一个整数
  2. 通过从每个数组中添加一个条目来创建一个非重复数组(如果它已经存在,则将它放在重复数组中)。
  3. 使用您自己的其他创意策略

答案 6 :(得分:0)

方法可能是这样的: 1.排序所有阵列。 2.对于每个阵列组合,请执行此操作

让我们考虑前两个阵列A,B。设A为A的大小。 还可以使用第三个数组或向量来存储结果

  for i=0-->a-1 {

   Search for A[i] in B   using    binarySearch.

   if A[i] exists in B then insert A[i] into our result vector

   }

对(B,C)和(C,A)重复相同的过程。

现在排序&amp;从末尾遍历结果向量,删除具有属性

的元素
     result[i] = result[i-1] 

最终的向量是必需的结果。

时间复杂性分析:

   T(n) = O(nlog(n)) for Sorting where n is the highest array size among the given three 

   For searching each element of an array in other sorted array T(n) = n * O(log n)

   T(n) = O(n (log n)) for sorting the result and O(n) for traversing 

   So overall time complexity is O(n log(n)); and space complexity is O(n)

请纠正我的错误

答案 7 :(得分:0)

在Java中:

不久就会写一个不使用java.utils。

同时使用java.utils的解决方案:

public static void twice(int[] a, int[] b, int[] c) {

    //Used Set to remove duplicates
    Set<Integer> setA = new HashSet<Integer>();
    for (int i = 0; i < a.length; i++) {
        setA.add(a[i]);
    }

    Set<Integer> setB = new HashSet<Integer>();
    for (int i = 0; i < b.length; i++) {
        setB.add(b[i]);
    }

    Set<Integer> setC = new HashSet<Integer>();
    for (int i = 0; i < c.length; i++) {
        setC.add(c[i]);
    }

    //Logic to fill data into a Map
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    for (Integer val : setA) {
        map.put(val, 1);
    }

    for (Integer val : setB) {
        if (map.get(val) != null) {
            int count = map.get(val);
            count++;
            map.put(val, count);
        } else {
            map.put(val, 1);
        }
    }

    for (Integer val : setC) {
        if (map.get(val) != null) {
            int count = map.get(val);
            count++;
            map.put(val, count);
        } else {
            map.put(val, 1);
        }
    }

    for (Map.Entry<Integer, Integer> entry2 : map.entrySet()) {

        //if (entry2.getValue() == 2) {  //Return the elements that are present in two out of three arrays.
        if(entry2.getValue() >= 2) {     //Return elements that are present **at least** twice in the three arrays.
            System.out.print(" " + entry2.getKey());
        }
    }
}

如果需要返回三个数组中的两个数组中存在的元素,则在最后一个for循环中更改条件。说:

int[] a = { 2, 3, 8, 4, 1, 9, 8 };
int[] b = { 6, 5, 3, 7, 9, 2, 1 };
int[] c = { 5, 1, 8, 2, 4, 0, 5 };

Output: { 3, 8, 4, 5, 9 }

答案 8 :(得分:0)

这里没有任何java.util库:

public static void twice(int[] a, int[] b, int[] c) {
    int[] a1 = removeDuplicates(a);
    int[] b1 = removeDuplicates(b);
    int[] c1 = removeDuplicates(c);

    int totalLen = a1.length + b1.length +c1.length;
    int[][] keyValue = new int[totalLen][2];

    int index = 0;
    for(int i=0; i<a1.length; i++, index++)
    {
        keyValue[index][0] = a1[i]; //Key
        keyValue[index][1] = 1;     //Value
    }

    for(int i=0; i<b1.length; i++)
    {
        boolean found = false;
        int tempIndex = -1;
        for(int j=0; j<index; j++)
        {
            if (keyValue[j][0] == b1[i]) {
                found = true;
                tempIndex = j;
                break;
            }
        }

        if(found){
            keyValue[tempIndex][1]++;
        } else {
            keyValue[index][0] = b1[i]; //Key
            keyValue[index][1] = 1;     //Value
            index++;
        }
    }

    for(int i=0; i<c1.length; i++)
    {
        boolean found = false;
        int tempIndex = -1;
        for(int j=0; j<index; j++)
        {
            if (keyValue[j][0] == c1[i]) {
                found = true;
                tempIndex = j;
                break;
            }
        }

        if(found){
            keyValue[tempIndex][1]++;
        } else {
            keyValue[index][0] = c1[i]; //Key
            keyValue[index][1] = 1;     //Value
            index++;
        }
    }

    for(int i=0; i<index; i++)
    {
        //if(keyValue[i][1] == 2)
        if(keyValue[i][1] >= 2)
        {
            System.out.print(keyValue[i][0]+" ");
        }
    }
}

public static int[] removeDuplicates(int[] input) {
    boolean[] dupInfo = new boolean[500];//Array should not have any value greater than 499.
    int totalItems = 0;

    for( int i = 0; i < input.length; ++i ) {
        if( dupInfo[input[i]] == false ) {
            dupInfo[input[i]] = true;
            totalItems++;
        }
    }

    int[] output = new int[totalItems];
    int j = 0;
    for( int i = 0; i < dupInfo.length; ++i ) {
        if( dupInfo[i] == true ) {
            output[j++] = i;
        }
    }
    return output;
}

答案 9 :(得分:0)

这很简单,可以用同样的方式为n个不同的数组完成:

    public static void compute(int[] a1, int[] a2, int[] a3) {
        HashMap<Integer, Integer> map = new HashMap<>();
        fillMap(map, a1);
        fillMap(map, a2);
        fillMap(map, a3);

        for (Integer key : map.keySet()) {
            System.out.print(map.get(key) > 1 ? key + ", " : "");
        }
    }

    public static void fillMap(HashMap<Integer, Integer> map, int[] a) {
        for (int i : a) {
            if (map.get(i) == null) {
                map.put(i, 1);
                continue;
            }
            int count = map.get(i);
            map.put(i, ++count);
        }
    }

答案 10 :(得分:0)

fun atLeastTwo(a: ArrayList<Int>, b: ArrayList<Int>, c: ArrayList<Int>): List<Int>{
    val map = a.associateWith { 1 }.toMutableMap()
    b.toSet().forEach { map[it] = map.getOrDefault(it, 0) + 1 }
    c.toSet().forEach{ map[it] = map.getOrDefault(it, 0) + 1 }
    return map.filter { it.value == 2 }.map { it.key }
}

答案 11 :(得分:0)

在 Javascript 中,你可以这样做:

let sa = new Set(),
    sb = new Set(),
    sc = new Set();
A.forEach(a => sa.add(a));
B.forEach(b => sb.add(b));
C.forEach(c => sc.add(c));
let res = new Set();
sa.forEach((a) => {
    if (sb.has(a) || sc.has(a)) res.add(a);
})
sb.forEach((b) => {
    if (sa.has(b) || sc.has(b)) res.add(b);
})
sc.forEach((c) => {
    if (sa.has(c) || sb.has(c)) res.add(c);
})
let arr = Array.from(res.values());
arr.sort((i, j) => i - j)
return arr