【问题标题】:Find numbers present in at least two of the three arrays查找三个数组中至少两个中存在的数字
【发布时间】:2014-03-06 20:32:45
【问题描述】:

我该如何解决以下问题:

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

例如:

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}

附:我对如何处理这个(“算法”)的建议感兴趣,而不是 Java 实用程序可能会给我答案

【问题讨论】:

    标签: java arrays algorithm


    【解决方案1】:
    1. a1 数字放入Map<Integer,Integer> count,使用值作为键,并将计数设置为1
    2. a2 数字放入同一张地图。如果某项不存在,则分配1的计数,否则将其分配现有计数+1
    3. a3 数字放入同一张地图。如果某项不存在,则分配1的计数,否则将其分配现有计数+1
    4. 遍历映射中的条目,并输出值大于 1 的所有键。

    该算法是在三个数组中元素的组合数量中摊销线性时间。

    如果三个数组中的数字被限制为 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);
        }
    }
    

    【讨论】:

    • 我想他想避免使用收藏库
    • 我猜这个答案会超出原始问题的学习曲线。换句话说,尚未到达地图章节。
    • @Sunil 我对此不确定——他说他正在寻找一种不使用 Java 实用程序的算法,但他对集合只字未提。不过,我将使用基于数组的解决方案进行扩展。
    • @Sunil OP 可以随时实现他自己的Map 实现,如果他想痛苦的话。
    • 如果数组有重复的元素,你的方法将不起作用
    【解决方案2】:

    您可以将这 3 个数组视为 sets,并找到某对集合的 intersection 中的每个元素。

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

    我同意这可能不是实现目标的最简单方法,但是能够将一个问题简化为另一个问题是每个程序员都应该掌握的技术,而且这个解决方案应该非常教育

    【讨论】:

    • 出色的解决方案
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      数学上可以这样解决:

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

      (S_1 intersect S_2) union (S_2 intersect S_3) union (S_3 intersect S_1)
      

      【讨论】:

        【解决方案5】:

        想想你可能会使用的问题和不同的策略:

        1. 遍历每个数组中的每个条目,如果该条目不在“重复”结果中,则查看该条目是否在剩余的每个数组中。如果是,则添加到重复项并返回下一个整数
        2. 通过从每个数组中添加一个条目来创建一个非重复数组(如果已经存在,则将其放入重复数组中)。
        3. 使用您自己的其他创意策略

        【讨论】:

          【解决方案6】:

          我喜欢画维恩图。您知道该图具有三个相交的圆圈,例如见here

          然后您会看到补语更容易描述: 那些只存在于一个数组中的元素是没有意义的。

          因此,您可以在哈希图中构建一个频率列表(即键 = 元素,值 = 在多少个数组中找到它的计数 [第一次]),然后在最后一遍中选择所有出现的元素不止一次。

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

          【讨论】:

            【解决方案7】:

            一种方法可能是这样的: 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) 重复相同的过程。

            现在从最后对结果向量进行排序和遍历,删除具有属性的元素

                 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)
            

            请指正我错了

            【讨论】:

              【解决方案8】:

              在 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 }
              

              【讨论】:

                【解决方案9】:

                这里没有任何 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;
                }
                

                【讨论】:

                  【解决方案10】:

                  这很简单,可以用同样的方式为 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);
                          }
                      }
                  

                  【讨论】:

                    【解决方案11】:
                    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 }
                    }
                    

                    【讨论】:

                      【解决方案12】:

                      在 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
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2020-03-26
                        • 2022-11-16
                        • 1970-01-01
                        • 2015-03-18
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-03-05
                        相关资源
                        最近更新 更多