我必须找到给定数字的偶数除数。为此,我尝试了。我得到正确的输出,但我得到的时间复杂度超过了要求。
问题: - 第一行包含测试用例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]);
}
}
答案 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循环运行一半次。