有效的查找方式数字的偶数除数总数

时间:2015-06-14 17:30:15

标签: java


我必须找到给定数字的偶数除数。为此,我尝试了。我得到正确的输出,但我得到的时间复杂度超过了要求。
问题: - 第一行包含测试用例T的数量,后面是T行,每行包含一个整数N
输出应该是 - 对于每个测试用例,请在一行中打印所需的答案
如何降低此给定代码的复杂性。或者任何人都可以建议更有效的方式 ...

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestClass {
    public static void main(String args[]) throws Exception {
        // Read input from stdin and provide input before running
        String frt = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();    
        int T = Integer.parseInt(line);     
        int[] inp = new int[T];
        for (int i = 0; i < T; i++) {           
            int x = Integer.parseInt(br.readLine());
            inp[i] = x;

        }
        int[] ans = new int[T];
        int count = 1;
        for (int i = 0; i < T; i++) {
            int x = inp[i];
            if (x % 2 == 0) {
                for (int j = 2; j <= x / 2; j = j + 2) {
                    if (x % j == 0)
                        count++;
                }
            } else
                count = 0;
            ans[i] = count;
        }
        for (int i = 0; i < T; i++)
            System.out.println(ans[i]);
    }

}

4 个答案:

答案 0 :(得分:2)

 import java.io.*;

 class Ideone
 {
    public static void main (String[] args) throws Exception
    {

      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      int T = Integer.parseInt(br.readLine());
      int i,j,k,n;

      int[] inp = new int[T];
      for (i = 0; i < T; i++) {
      inp[i] = Integer.parseInt(br.readLine());
      }

     //Find all the primes numbers till the square-root of 10^9.
     int MAX, root, arrLen;
     MAX=1000000000;
     arrLen=(int)Math.sqrt(MAX);  // arrLen=31622 
     boolean[] primes=new boolean[arrLen+2]; // No need to find all the primes numbers till MAX

     primes[0]=primes[1]=false;
     for(i=2;i<arrLen;i++)
           primes[i]=true;


     // Using Sieve of Eratosthenes
    // Square root of 31622 is 177.8
    root=(int)Math.sqrt(arrLen); // root=177
    for(i=2;i<=root;i++)
    {
       if(primes[i])
       {
           n=i*i;
           k=0;

           //arrLen is the length of primes array.
           for(j=n; j<arrLen; k+=1, j=n+(i*k))
                  primes[j]=false;
       }
   }

    int[] ans = new int[T];
    for( i = 0; i < T; i++) {
         n = inp[i];

         if(n%2==1)
         {
             ans[i]=0; // Odd numbers will have 0 even divisors
         }
         else
         {

          int[] facts=new int[50];
          for(k=0;k<50;k++)
              facts[k]=1;

        facts[0]=0; // fact[0] will contain the highest power of 2 that divides n.
        while(n%2==0)
        {
             facts[0]+=1;
             n=n/2;
        }           

        // Prime factorizing n
        j=1;
        for( k=3; k<arrLen; k+=2)
        {
            if(primes[k] && n%k==0)
            {
                while(n%k==0)
               {
                    facts[j]+=1;
                    n=n/k;
               }
               j+=1;
            }
            if(n==1)  // To check if n has been completely divided or not.
               break;
       }

       if(n!=1) // To check if there is any prime factor greater than the square root of MAX.
       {
            facts[j]+=1;
            j+=1;
       }

       int count=1;
       for(k=0;k<j;k++)
            count=count*facts[k];

        ans[i]=count;
       }
}

   for ( i = 0; i < T; i++)
           System.out.println(ans[i]);

     }
 }

我觉得这个问题可能已发布在任何竞争性编码平台上,可能就像HackerEarth一样。如果是这样,那么请不要在StackOverFlow上发布直接问题(在我看来)。 无论如何,我已经测试了我的代码,它运行正常。 在无法减少时间复杂度的问题中,首先要确保不会创建不必要的对象。在存储器中创建对象是耗时的操作。避免无关的对象和变量的创建。上面的代码仍然可以优化,但这会降低它的可读性。 :)

在解决问题之前,请尝试找出各种测试用例。像奇数一样,将有0偶数除数。因此通过检查一个数字是否为奇数,可以减少几个操作。

对上述代码的更多解释: A数的除数是:(N1 + 1)(N2 + 1)(N3 + 1)......其中N1,N2,N3等是该数的素数倍数的幂。 现在如果N1是2(唯一偶数素数), 那么数的偶数除数是:N1 *(N2 + 1)*(N3 + 1)......

在fact []数组中,fact [0]对应N1,而N2,N3等存储在事实[1],事实[2]等中。 事实[0]初始化为0,而其他事件初始化为1。 计数存储最终乘积:N1 *(N2 + 1)*(N3 + 1)...等于原始数的偶数除数。

答案 1 :(得分:0)

有一个非常简单的技巧,首先计算720的素数分解,即2^4×3^2×5,这里的因子总数为3x2×5=30,以及奇数因子的数量(奇素数的因子数)= 3×2=6,减去给出偶数因子的数量= 24。此方法适用于任何数字。

注意:如果数字没有奇数因子,即素数因子化的形式为2a,则偶数因子数为a,奇数因子数为1。

答案 2 :(得分:0)

我的解决方案,更短,更简单:

public class Solution {

    public static int numberOfEvenDivisors(int n) {
        if (n % 2 == 1)
            return 0;
        int evenDivisors = 0;
        for (int i = 1; i < Math.sqrt(n) + 1; i++) {
            if ((i % 2 == 0) && (n % i == 0))
                evenDivisors++;
            if ((n % (n / i) == 0) && (n / i) % 2 == 0)
                evenDivisors++;
            if ((i * i == n) && (i % 2 == 0))
                evenDivisors--;
        }
        return evenDivisors;
    }

    public static void main(String[] args) {
        //test here 
    }
}

这里是简短的解释: 当n为奇数时,我们返回0,因此没有偶数。 在第一个if中,我们检查i是否除数,i是否为偶数。如果是,则增加除数计数器。请注意,我们从1开始。这是必要的,因为在这里我们知道n是偶数,而n是它自己的除数。

如果if是偶数且n / i是除数,则在第二个i中增加除数计数器。如果i是偶数,则我们已经在第一个if中对其进行了计数。并且我们知道(n/i) >= i,因为我们只计算i的最高n的平方根。

在最后的第三个if中,我们检查i是否是n的平方根的偶数除数(例如i == 4,{{1 }}。在这里,我们减少除数的数量是因为我们不想两次计数相同的除数。那是。 附言我们假设n == 16

答案 3 :(得分:-2)

这个for循环

for (int i = 0; i < T; i++) {
        int x = inp[i];
        if (x % 2 == 0) {
            for (int j = 2; j <= x / 2; j = j + 2) {
                if (x % j == 0)
                    count++;
        } else
            count = 0;
        ans[i] = count;
    }

可以更改为

for (int i = 0; i < T; i+=2) {
        int x = inp[i];
        for (int j = 2; j <= x / 2; j = j + 2) {
            if (x % j == 0)
                count++;
        if(count != 1)
            count = 0;
        ans[i] = count;
    }

这样就可以使for循环运行一半次。