Java 如何优化此代码以减少计算时间

Java 如何优化此代码以减少计算时间,java,algorithm,Java,Algorithm,我在解决一个问题,这个问题要求我打印一个整数数组中的所有数字,其中包含1,2,3。例如,一个包含[123300,456789]的数组将输出为[123300]。 在我的代码中,我使用了ArrayList和所有需要解决它的东西。不过,评估时间还没有达到标准 public static void take(int[] a) { ArrayList<Integer> ai = new ArrayList<>(); for(int i=0; i<a.leng

我在解决一个问题,这个问题要求我打印一个整数数组中的所有数字,其中包含1,2,3。例如,一个包含[123300,456789]的数组将输出为[123300]。 在我的代码中,我使用了ArrayList和所有需要解决它的东西。不过,评估时间还没有达到标准

public static void take(int[] a) 
{
    ArrayList<Integer> ai = new ArrayList<>();
    for(int i=0; i<a.length;i++) 
    {
        int temp =a[i];
        while(a[i]>0) 
        {
            int b=a[i]%10;
            if(b==1||b==2||b==3) 
            {
                ai.add(temp);
                break;
            }
            a[i]= a[i]/10;
        }
    }
    if(ai.isEmpty()) 
    {
        System.out.println(-1);
    }
    else 
    {
        ai.sort(null);
        System.out.println(ai);
    }
}

public static void main(String[] args) 
{
    Scanner mew = new Scanner(System.in);
    int t=mew.nextInt();
    for(int i=0; i<t;i++) 
    {
        int n=mew.nextInt();
        int a[] = new int[n];
        for(int j=0; j<n;j++) 
        {
           a[j] = mew.nextInt();
        }
        take(a);
    }
}
publicstaticvoidtake(int[]a)
{
ArrayList ai=新的ArrayList();
对于(int i=0;i0)
{
int b=a[i]%10;
如果(b==1 | | b==2 | | b==3)
{
ai.添加(临时);
打破
}
a[i]=a[i]/10;
}
}
if(ai.isEmpty())
{
系统输出打印项数(-1);
}
其他的
{
ai.sort(空);
系统输出打印LN(ai);
}
}
公共静态void main(字符串[]args)
{
扫描器mew=新扫描器(System.in);
int t=mew.nextInt();

对于(int i=0;i您只需将
数字
转换为字符串;检索所有字符,并使用
Set
检查所需字符是否存在:

public static Set<Integer> take(int[] a, char[] markers) {
    Set<Integer> numbers = new TreeSet<>();

    for (int i = 0; i < a.length; i++) {
        String str = String.valueOf(a[i]);

        for (char marker : markers) {
            if (str.contains(String.valueOf(marker))) {
                numbers.add(a[i]);
                break;
            }
        }
    }

    return numbers;
}
publicstaticset-take(int[]a,char[]markers){
设置编号=新树集();
for(int i=0;i
作为替代方案,您可以使用流:

public static Set<Integer> take(int[] a, char[] markers) {
    return Arrays.stream(a)
                 .boxed()
                 .filter(val -> {
                     String str = String.valueOf(val);

                     for (char marker : markers)
                         if (str.contains(String.valueOf(marker)))
                             return true;

                     return false;
                 })
                 .sorted()
                 .collect(Collectors.toSet());
}
publicstaticset-take(int[]a,char[]markers){
返回数组.stream(a)
.boxed()
.filter(val->{
String str=String.valueOf(val);
用于(字符标记:标记)
if(str.contains(String.valueOf(marker)))
返回true;
返回false;
})
.已排序()
.collect(收集器.toSet());
}
对此使用哈希。。。
使用键1、2和3创建hashmap。如果我理解正确,那么许多数字将被删除。

如果数字1、2或3至少出现一次,您希望通过文本搜索。您可以使用如下正则表达式执行此操作:

import java.util.*;

public class So {
    public static void searchForNumbers(int[] sourceArray) {
        System.out.println("source array = " + Arrays.toString(sourceArray));
        List<Integer> ai = new ArrayList<>();
        for (int i = 0; i < sourceArray.length; i++) {
            if( Integer.toString(sourceArray[i]).matches(".*[1-3].*")) {
                ai.add(sourceArray[i]);
            }
        }
        if (ai.isEmpty()) {
            System.out.println(-1);
        } else {
            ai.sort(Comparator.naturalOrder());
            System.out.println(ai);
        }
    }

    public static void main(String[] args) {
        Scanner mew = new Scanner(System.in);
        int numberOfTimesToAskForNumbers = mew.nextInt();
        System.out.println("numberOfTimesToAskForNumbers = " + numberOfTimesToAskForNumbers);
        for (int i = 0; i < numberOfTimesToAskForNumbers; i++) {
            int amountOfNumbersInThisRound = mew.nextInt();
            System.out.println("amountOfNumbersInThisRound = " + amountOfNumbersInThisRound);
            int a[] = new int[amountOfNumbersInThisRound];
            for (int j = 0; j < amountOfNumbersInThisRound; j++) {
                a[j] = mew.nextInt();
                System.out.println("a[j] = " + a[j]);
            }
            searchForNumbers(a);
        }
    }
}
import java.util.*;
公开课{
公共静态void searchForNumbers(int[]sourceArray){
System.out.println(“源数组=“+Arrays.toString(sourceArray));
列表ai=新的ArrayList();
for(int i=0;i
我还重新命名了变量,使其更加清晰,并添加了额外的打印输出,以便在命令行的交互过程中获得反馈


旁注:像这样的事情真的应该通过单元测试来测试,以确保所有情况都正常,而不必一直手动键入内容进行测试。

您的目标过于复杂。效率的第一条规则是“避免做额外的工作”。以下是代码工作过度的地方:

  • 您从输入中读取字符,将其解析为整数,然后将数字重新分解为数字,以对照1、2和3检查每个字符
  • 构建候选数组,然后测试数组的每个元素,但不需要数组本身,因为您只对通过1-2-3测试的候选对象感兴趣
我下面的代码避免了额外的工作,并使用稍微更有效的测试来检查1、2或3的存在。这将导致显著的加速:

import java.util.*;

public class J {

    public static boolean has1or2or3(String s) {
        for (char c : s.toCharArray()) 
            if (c >= '1' && c <= '3') return true;
        return false;
    }

    public static void solve(Scanner in) {
        int cases = in.nextInt();
        while (cases-- > 0) {

            // read input, solve problem
            ArrayList<Integer> good = new ArrayList<>();
            int count = in.nextInt();
            for (int i=0; i<count; i++) {
                String candidate = in.next();
                if (has1or2or3(candidate)) {
                    good.add(Integer.parseInt(candidate));
                }
            }

            // generate output
            if (good.isEmpty()) {
                System.out.println(-1);
            } else {
                Collections.sort(good);
                for (int c : good) {
                    System.out.print(c + " ");
                }
                System.out.println();
            }
        }
    }

    public static void main(String[] args) {
        try (Scanner in = new Scanner(System.in)) {
            solve(in);
        }
    }   
}


问:你说的“不合格”到底是什么意思?到目前为止,您采用了什么计时方式?建议:尝试一个简单的循环,将每个数字转换为字符串,并检查字符“1”、“2”或“3”。将计时方式与原始版本进行比较。是否需要排序?如果您的代码工作正常且速度有点慢,您可能应该尝试codereview.stackexchange.comNot Up the mark meanin我想你可以把这个和另一个答案结合起来,使用
.filter(str->str.matches(“.[1-3].]))
谢谢,这是一个很好的解决方案,但我的问题并不是针对这个问题的。我可以知道如何减少解决方案的编译时间,就像一些基本规则一样吗?就效率而言,流和额外的数据结构(如集合)是多余的。可读性当然会提高,但这并不是最初的目标。如果时间是在一个premium,正则表达式比单个字符传递慢。即使JVM以后可能会对其进行优化,他们也需要在前10k左右的迭代中编译和执行正则表达式。构建hashmap不是答案。虽然它可以工作,但数字的hashmap比大小为10的int数组便宜得多。而且,因为我们只对查找无论是1、2还是3,你都不需要数组。当你需要高效的代码时,使用额外的数据结构并不需要数组
1
6
4567 345 1122 89458 8495 473
345 473 1122