检查图表是否存在(java)

时间:2018-03-10 00:17:23

标签: java graph

确定是否存在具有顶点度数序列的图形(s = s1,s2 ... sn)。 什么是解决此问题的最佳和最优化的算法。

 Input:
    the first line contains `t<100` - amount of sequnces.
    the second line contains value `n <= 1000000`(length of a sequence).
    the third line contains  contains `n` non-negative integer numbers. And so on.
Output:
    if the graph can exist print "yes" otherwise print "no".
For example: 
Input:
3
5
1 2 3 2 1
4
3 3 2 2
3
1 3 2
Output:
No
Yes
Yes

最长执行时间应为0.4秒。 这是我的代码(如果奇数顶点的数量是偶数,则图表存在):

    import java.util.Scanner;
public class Main {
      public static final Scanner in = new Scanner(System.in);
    public static void isGraph (int []a, int n) {
        int k=0;
        for(int i=0; i< n; i++) {
            if(a[i] %2 != 0) {
                k++;
            }
        }
        if(k%2 == 0)
           System.out.println("Yes");
        else
            System.out.println("No");

    }
    public static void main(String[] args) throws Exception{
        double t1 = System.nanoTime();
        int n;
        int []a;
        int t = Integer.parseInt(in.nextLine());
        while(t-- > 0) {
            n = in.nextInt();
            a = new int[n];
            for(int i=0; i<n; i++)
                a[i] = in.nextInt();
            isGraph(a,n);
        }
        System.out.println(System.nanoTime() - t1);
    }
}

但该程序的执行时间超过0.4秒。我的运行时间超出了。我如何优化代码并加快运行时间。可能还有另一种算法来解决这个任务,请帮帮我。

2 个答案:

答案 0 :(得分:2)

我想我有更快捷的方式。请验证这一点。如果你担心偶数/奇数的最终结果,那么似乎没有理由跟踪k计数器。您可以保持运行顺序是偶数还是奇数的动态值:

public static void isGraph (int []a, int n) {
    int k = 0;
    for(int i=0; i< n; i++) {
        k += a[i] & 1;
    }
    if(k%2 == 0)
        System.out.println("Yes");
    else
        System.out.println("No");

}

这可能有助于你的阅读:我没有经验,但是我从竞赛网站上得到了它:

阅读速度缓慢:

/** Read count integers using Scanner */
static int scanInteger(int count) {
    Scanner scanner = new Scanner(input);
    int last = 0;
    while (count-- > 0) {
        last = scanner.nextInt();
    }
    return last;
 }

更快的方式:

static int readIntegers(int count) 
    throws IOException {
    BufferedReader reader = new BufferedReader(
           new InputStreamReader(input) );
    StringTokenizer tokenizer = new StringTokenizer("");
    int last = 0;
    while (count-- > 0) {
        if (! tokenizer.hasMoreTokens() ) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        last = Integer.parseInt(tokenizer.nextToken());
    }
    return last;
}

编辑:展示如何避免阶段1为读取循环的两个阶段,阶段2为算法:

public static void main(String[] args) throws Exception{
    double t1 = System.nanoTime();
    int n;
    // int []a;  //  Not necessary
    int t = Integer.parseInt(in.nextLine());
    while(t-- > 0) {
        n = in.nextInt();
        // a = new int[n];  // Not necessary
        int k = 0;
        int a;
        for(int i=0; i<n; i++) {
            a = in.nextInt();
            k += a & 1;
        }
        // isGraph(a,n);  // Not necessary
        if(k % 2 == 0)
            System.out.println("Yes");
        else
            System.out.println("No");
    }
    System.out.println(System.nanoTime() - t1);
}

答案 1 :(得分:0)

  

可能还有另一种解决此任务的算法

那不是问题(IMO)。

提示1:既然您事先知道序列的长度,就可以创建数组并以比这更快的速度解析序列:

  a = Arrays.stream(s.split(" ")).mapToInt(Integer::parseInt).toArray();

(Java 8+流很优雅,但它们不是最快的方式。)

提示2:使用Scanner可能比读取字符串并解析它们更快。

提示3:您可能完全避免创建数组。 (这将是不良的编码实践IMO ...但如果性能至关重要......)