Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对于N个大小相等且整数升序的数组,如何选择数组的公共数字?_Java_Algorithm - Fatal编程技术网

Java 对于N个大小相等且整数升序的数组,如何选择数组的公共数字?

Java 对于N个大小相等且整数升序的数组,如何选择数组的公共数字?,java,algorithm,Java,Algorithm,今天在一次采访中,我被问到一个算法问题,我很想得到各位成员的意见。问题如下: 给定大小相同且整数升序为整数的N个数组,如何选择所有N个数组的公共数字 起初,我的想法是迭代元素,从第一个数组开始,一直到数组的其余部分。但如果我是对的,那将导致N次N次迭代。因此,我想出了一个解决方案,通过将元素作为键,值作为计数器,将计数添加到映射中。这样,我相信时间复杂度仅为N。下面是我的方法在Java中的实现 public static void main(String[] args) { int[]

今天在一次采访中,我被问到一个算法问题,我很想得到各位成员的意见。问题如下:

给定大小相同且整数升序为整数的N个数组,如何选择所有N个数组的公共数字

起初,我的想法是迭代元素,从第一个数组开始,一直到数组的其余部分。但如果我是对的,那将导致N次N次迭代。因此,我想出了一个解决方案,通过将元素作为键,值作为计数器,将计数添加到映射中。这样,我相信时间复杂度仅为N。下面是我的方法在Java中的实现

public static void main(String[] args) {

    int[] arr1 = { 1, 4, 6, 8,11,15 };
    int[] arr2 = { 3, 4, 6, 9, 10,16 };
    int[] arr3 = { 1, 4, 6, 13,15,16 };
    System.out.println(commonNumbers(arr1, arr2, arr3));
}

public static List<Integer> commonNumbers(int[] arr1, int[] arr2, int[] arr3) {
    Map<Integer, Integer>countMap = new HashMap<Integer, Integer>();

    for(int element:arr1)
    {
        countMap.put(element, 1);
    }

    for(int element:arr2)
    {
        if(countMap.containsKey(element))
        {
            countMap.put(element,countMap.get(element)+1);
        }
    }

    for(int element:arr3)
    {
        if(countMap.containsKey(element))
        {
            countMap.put(element,countMap.get(element)+1);
        }
    }

    List<Integer>toReturn = new LinkedList<Integer>();

    for(int key:countMap.keySet())
    {
        int count = countMap.get(key);
        if(count==3)toReturn.add(key);
    }

    return toReturn;
}
publicstaticvoidmain(字符串[]args){
int[]arr1={1,4,6,8,11,15};
int[]arr2={3,4,6,9,10,16};
int[]arr3={1,4,6,13,15,16};
System.out.println(公共编号(arr1、arr2、arr3));
}
公共静态列表CommonNumber(int[]arr1、int[]arr2、int[]arr3){
MapcountMap=新HashMap();
for(int元素:arr1)
{
countMap.put(元素,1);
}
for(int元素:arr2)
{
if(countMap.containsKey(元素))
{
countMap.put(元素,countMap.get(元素)+1);
}
}
for(int元素:arr3)
{
if(countMap.containsKey(元素))
{
countMap.put(元素,countMap.get(元素)+1);
}
}
ListtoReturn=新建LinkedList();
for(int键:countMap.keySet())
{
int count=countMap.get(键);
如果(计数==3)返回。添加(键);
}
回归回归;
}
我只是对三个阵列进行了测试,以了解它将如何工作。虽然我认为这仍然适用,但问题讨论的是N数组


我的问题是,考虑到时间复杂性,有没有更好的方法来解决这个问题?

将其视为3个队列。值不同时,“remove”(通过增加数组索引)最小。当它们匹配时,“删除”(并记录)匹配

int i1 = 0;
int i2 = 0;
int i3 = 0;

while (i1 < array1.size && i2 < array2.size && i3 < array3.size) {
    int next1 = array1[i1];
    int next2 = array2[i2];
    int next3 = array3[i3];

    if (next1 == next2 && next1 == next3) {
        recordMatch(next1);
        i1++;
        i2++;
        i3++;
    }
    else if (next1 < next2 && next1 < next3) {
        i1++;
    }
    else if (next2 < next1 && next2 < next3) {
        i2++;
    }
    else {
        i3++;
    }
}
inti1=0;
int i2=0;
int i3=0;
而(i1

很容易推广到N个数组,但是对于N个较大的数组,您可能希望以某种方式优化比较(NPE的“堆”)。

我认为这可以通过对N个数组和N个元素进行单个并行迭代来解决。在堆中,您将保留N个输入数组中每个数组的当前元素

其思想是,在每一步中,您都要沿着元素位于堆顶部(即最小)的数组前进

您需要能够检测堆何时由完全相同的值组成。只要跟踪添加到堆中的最大元素,这可以在固定时间内完成


如果每个数组包含M个元素,最坏情况下的时间复杂度将是
O(M*N*log(N))
,它需要
O(N)
内存。

好的-这里可能有点幼稚,但我认为线索是数组是按升序排列的。我的java已经生锈了,但这里有一些psedoocode。我还没有测试过它,所以它可能并不完美,但它应该是一种快速的方法:

I = 1
J = 1
K = 1

While I <= Array1Count and J <= Array2Count and K <= Array3Count

   If Array1(I) = Array2(J)
      If Array1(I) = Array3(K)
         === Found Match
         I++
         J++
         K++
      else
         if Array1(I) < Array3(K)
            I++
         end if
      end if
   else
      If Array1(I) < Array2(J)
         I++
      else
         if Array2(J) < Array3(K)
            J++
         else
            K++
         end if
      end if
   end if
Wend
I=1
J=1
K=1

我认为另一种方法与我们在Mergesort中所做的类似:同时遍历所有数组,得到相同的数字。这将利用数组是按排序顺序排列的这一事实,并且除了输出数组之外不会使用额外的空间。如果只需要打印常用数字,则不需要额外的空间

public static List<Integer> commonNumbers(int[] arrA, int[] arrB, int[] arrC) {
   int[] idx = {0, 0, 0};

   while (idxA<arrA.length && idxB<arrB.length && idxC<arrC.length) {
      if ( arrA[idx[0]]==arrB[idx[1]] && arrB[idx[1]]==arrC[idx[2]] ) {
          // Same number
          System.out.print("Common number %d\n", arrA[idx[0]]);
          for (int i=0;i<3;i++)
              idx[i]++;
      } else {
          // Increase the index of the lowest number
          int idxLowest = 0; int nLowest = arrA[idx[0]];
          if (arrB[idx[1]] < nLowest) {
             idxLowest = 1;
             nLowest = arrB[idx[1]];
          }
          if (arrC[idx[2]] < nLowest) {
             idxLowest = 2;
          }
          idx[idxLowest]++;
      }
   }
}
公共静态列表公共编号(int[]arrA,int[]arrB,int[]arrC){
int[]idx={0,0,0};
而(idxAtry

公共静态集合commonNumber(int[]arr1、int[]arr2、int[]arr3){
Set s1=createSet(arr1);
Set s2=创建集(arr2);
Set s3=创建集(arr3);
s1.保留(s2);
s1.保留(s3);
返回s1;
}
私有静态集createSet(int[]arr){
Set s=新的HashSet();
对于(内部e:arr){
s、 加(e);
}
返回s;
}

这是我在算法类中学习的方法。不确定它是否“更好”,但它使用更少的内存和开销,因为它直接遍历数组,而不是首先构建映射

public static List<Integer> commonNumbers(int[] arr1, int[] arr2, int[] arr3, ... , int[] arrN) {
    List<Integer>toReturn = new LinkedList<Integer>();

    int len = arr1.length;
    int j = 0, k = 0, ... , counterN = 0;
    for (int i = 0; i < len; i++) {
        while (arr2[j] < arr1[i] && j < len) j++;
        while (arr3[k] < arr1[i] && k < len) k++;
        ...
        while (arrN[counterN] < arr1[i] && counterN < len) counterN++;
        if (arr1[i] == arr2[j] && arr2[j] == arr3[k] && ... && arr1[i] == arrN[counterN]) {
            toReturn.add(arr1[i]);
        }
    }

    return toReturn;
}
公共静态列表公共编号(int[]arr1,int[]arr2,int[]arr3,…,int[]arrN){
ListtoReturn=新建LinkedList();
int len=arr1.1长度;
int j=0,k=0,…,计数器n=0;
对于(int i=0;i
您的解决方案是可以接受的,但它使用NxM空间。您可以使用O(N)空间(其中N是数组的数量)或O(1)空间

解决方案#1(Luigi Mendoza)


假设有许多小数组(M,这可以在
O(M*N)
中解决,M是数组的长度

让我们看看
N=2
会发生什么,这将是一个排序列表交集问题,在
O(l1+l2)
时间内运行一个经典的类似合并的解决方案。(l1=第一个数组的长度,l2=第二个数组的长度)。(了解更多信息。)

现在,让我们在一个归纳m中重新迭代算法N次
public static List<Integer> commonNumbers(int[] arr1, int[] arr2, int[] arr3, ... , int[] arrN) {
    List<Integer>toReturn = new LinkedList<Integer>();

    int len = arr1.length;
    int j = 0, k = 0, ... , counterN = 0;
    for (int i = 0; i < len; i++) {
        while (arr2[j] < arr1[i] && j < len) j++;
        while (arr3[k] < arr1[i] && k < len) k++;
        ...
        while (arrN[counterN] < arr1[i] && counterN < len) counterN++;
        if (arr1[i] == arr2[j] && arr2[j] == arr3[k] && ... && arr1[i] == arrN[counterN]) {
            toReturn.add(arr1[i]);
        }
    }

    return toReturn;
}
public static List<Integer> getCommon(List<List<Integer>> list){
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    int c=0;
    for (List<Integer> is : list) {
        c++;
        for (int i : is) {
            if(map.containsKey(i)){
                map.put(i, map.get(i)+1);
            }else{
                map.put(i, 1);
            }
        }
    }
     List<Integer>toReturn = new LinkedList<Integer>();
    for(int key:map.keySet())
    {
        int count = map.get(key);
        if(count==c)toReturn.add(key);
    }
    return toReturn;
}