Java 如何找到3个数组中常见的最小数?

Java 如何找到3个数组中常见的最小数?,java,arraylist,time-complexity,complexity-theory,Java,Arraylist,Time Complexity,Complexity Theory,问题是: Given 3 random arrays of integers, write a method to find the smallest number that is common among the 3 arrays. HINT: Sort first and just traverse first few elements until you reach the common number [-1,-2, 4,5,6,1,2,3,3,3,1,1,1] [54,6,7,8

问题是:

Given 3 random arrays of integers, write a method to find the smallest number that is common among the 3 arrays. HINT: Sort first and just traverse first few elements until you reach the common number
  [-1,-2, 4,5,6,1,2,3,3,3,1,1,1]
  [54,6,7,8,1,3,5,1]
  [1,6,9,1,0,2,1]
  result = 1
我写了一个可行的解决方案代码,但我想知道是否有更简单、更有效的方法来实现这一点

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

public class Smcomm {

    public static void main(String[] args) {
        int[] A = {-1,-2,4,5,6,1,2,3,3,3,1,1,1};
        int[] B = {54,6,7,8,1,3,5,1};
        int[] C = {1,6,9,1,0,2,1};

        ArrayList<Integer> ar1 = new ArrayList<Integer>();
        ArrayList<Integer> ar2 = new ArrayList<Integer>();
        ArrayList<Integer> ar3 = new ArrayList<Integer>();

        for(int el: A){
            ar1.add(el);
        }

        for(int el: B){
            ar2.add(el);
        }

        for(int el: C){
            ar3.add(el);
        }

        Collections.sort(ar1);
        Collections.sort(ar2);
        Collections.sort(ar3);

        printer(ar1);
        printer(ar2);
        printer(ar3);

        finder(ar1,ar2,ar3);





    }


    static void printer(ArrayList ar){

        Iterator<Integer> it = ar.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("--------------------");
    }

    static void finder(ArrayList ar1, ArrayList ar2, ArrayList ar3){
        ar1.retainAll(ar2);
        ar1.retainAll(ar3);
        if(ar1.size()>0){
            System.out.println(ar1.get(1));
        }else {
            System.out.println("no comm el");
        }
    }

}
import java.util.ArrayList;
导入java.util.Collections;
导入java.util.Iterator;
公共类Smcomm{
公共静态void main(字符串[]args){
int[]A={-1,-2,4,5,6,1,2,3,3,1,1,1};
int[]B={54,6,7,8,1,3,5,1};
int[]C={1,6,9,1,0,2,1};
ArrayList ar1=新的ArrayList();
ArrayList ar2=新的ArrayList();
ArrayList ar3=新的ArrayList();
对于(整数el:A){
ar1.加入(el);
}
对于(内部el:B){
ar2.加入(el);
}
对于(整数el:C){
ar3.加入(el);
}
Collections.sort(ar1);
集合。排序(ar2);
集合。排序(ar3);
打印机(ar1);
打印机(ar2);
打印机(ar3);
查找器(ar1、ar2、ar3);
}
静态无效打印机(ArrayList ar){
迭代器it=ar.Iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println(“------------------”);
}
静态空洞查找器(ArrayList ar1、ArrayList ar2、ArrayList ar3){
ar1.保留(ar2);
ar1.保留(ar3);
如果(ar1.size()>0){
System.out.println(ar1.get(1));
}否则{
System.out.println(“无通信”);
}
}
}
无法完全说服我的方法是保留,因为我认为它的复杂性为O(n^2)

我不需要找到所有的元素,但我只想找到最小的元素。您是否知道,当该方法在数组中找到第一个公共元素时,是否有可能以某种方式停止该方法的执行?这应该不难,因为数组已经排序了


感谢您的帮助。

首先,不需要将数组转换为s(因为您不需要使用,它可以找到3个数组的所有公共元素,这超出了您的需要)

数组(或列表)的排序似乎是确保最坏情况复杂性为O(NlogN)所必需的。我不相信你能做得比那更好

一旦有了3个已排序的数组,就可以使用3个索引(每个数组一个)通过单个while循环迭代3个数组,直到找到所有3个数组中出现的第一个元素。这将需要线性时间


最后一件事-您当前的解决方案有一个小错误-它应该输出
ar1.get(0)
,而不是
ar1.get(1)
,这是一种稍微不同的方法:

  • 将最短数组转换为排序集
  • 将另外两个数组转换为普通集合
  • 迭代该排序集,对于每个条目,检查其他两个集合是否包含它
其他两个包含的第一个数字必须是最小的公共条目。这可以防止您查看重复的条目(在这里这并不重要),并且还可以避免对所有三个数组进行排序


最后,对于这样的小例子,任何正确的解决方案都足够好了。不同解决方案的潜在权衡只有在您谈论的列表中有数千条、甚至数百万条条目时才起作用

您只能使用数组和foreach循环以简单的方式实现这一点:

  • 排序数组
  • 循环通过数组A,移动B和C,直到数字大于A
  • 检查它们是否相等,否则转到下一个数字,但避免再次遍历相同的索引,从停止的位置继续
以下是如何实现这一目标的示例:

public static void main(String[] args) {
    int[] A = {-1, -2, 4, 5, 6, 1, 2, 3, 3, 3, 1, 1, 1};
    int[] B = {54, 6, 7, 8, 1, 3, 5, 1};
    int[] C = {1, 6, 9, 1, 0, 2, 1};

    Arrays.sort(A);
    Arrays.sort(B);
    Arrays.sort(C);

    Optional<Integer> inCommon = findInCommon(A, B, C);

    if (inCommon.isPresent()) {
        System.out.println(inCommon.get());
    } else {
        System.out.println("no comm el");
    }
}

private static Optional<Integer> findInCommon(int[] A, int[] B, int[] C) {
    int lastB = 0;
    int lastC = 0;

    for (int valA : A) {
        while (B[lastB] < valA) lastB++;
        while (C[lastC] < valA) lastC++;

        if (valA == B[lastB] && valA == C[lastC]) {
            return Optional.of(valA);
        }
    }
    return Optional.empty();
}
publicstaticvoidmain(字符串[]args){
int[]A={-1,-2,4,5,6,1,2,3,3,3,1,1,1};
int[]B={54,6,7,8,1,3,5,1};
int[]C={1,6,9,1,0,2,1};
数组。排序(A);
数组。排序(B);
数组。排序(C);
可选inCommon=findInCommon(A、B、C);
if(inCommon.isPresent()){
System.out.println(inCommon.get());
}否则{
System.out.println(“无通信”);
}
}
私有静态可选findInCommon(int[]A,int[]B,int[]C){
int lastB=0;
int lastC=0;
对于(int valA:A){
而(B[lastB]
使用Java 8 streams的另一种方法,计算交叉点,然后找到最小值:

 List<Integer> list1 = Arrays.asList(A);
 List<Integer> list2 = Arrays.asList(B);
 List<Integer> list3 = Arrays.asList(C);

 Set<Integer> commonElements = list1.stream().filter(list2::contains).filter(list3::contains).collect(Collectors.toSet());
 int minimumCommonElement = Collections.min(commonElements);
List list1=Arrays.asList(A);
List list2=Arrays.asList(B);
list3=Arrays.asList(C);
设置commonElements=list1.stream().filter(list2::contains).filter(list3::contains).collect(Collectors.toSet());
int minimumCommonElement=Collections.min(commonElements);

我认为实现这一点的最简单方法是将元素存储在树集中(自然排序并删除重复项),而不是存储在ArrayList中,然后遍历集合1的每个元素,直到找到所有3个集合中都存在的元素

static void finder(Set<Integer> s1, Set<Integer> s2, Set<Integer> s3) {
    boolean found=false;
    for (int i: s1) {
        if (s2.contains(i) && s3.contains(i)) {
            System.out.println(i);
            found=true;
            break;
        }
    }
    if (!found) {
        System.out.println("no comm el");
    }
}
static void finder(组s1、组s2、组s3){
布尔值=false;
对于(int i:s1){
如果(s2包含(i)和&s3包含(i)){
系统输出打印LN(i);
发现=真;
打破
}
}
如果(!找到){
System.out.println(“无通信”);
}
}

以下操作非常有效。我突然想到,您只需要对其中一个列表进行排序,并将其用作交互的源

列表列表1=新的ArrayList(
(1、-2、4、5、6、3、1、2、3、3、3、1、1、1、1);
List list2=新的数组列表(List.of(54,6,7,8,-4,1,3,5,1));
List list3=新的数组列表(List.of(1,6,9,1,0,-4,2,1));
Collections.sort(列表1);
for(int e:list1){
if(列表2.contains(e)&列表3.contains(e)){
系统输出打印ln(e);