[英]Reducing the time complexity/Optimizing the solution
座右銘是找到N以下3或5的所有倍數的和。
這是我的代碼:
public class Solution
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int t = in.nextInt();
long n=0;
long sum=0;
for(int a0 = 0; a0 < t; a0++)
{
n = in.nextInt();
sum=0;
for(long i=1;i<n;i++)
{
if(i%3==0 || i%5==0)
sum = sum + i;
}
System.out.println(sum);
}
}
}
對於某些測試用例,要花費超過1秒的時間。 誰能幫助我,以減少時間的復雜性?
我們可以找到小於N
的所有d
的所有倍數的和,作為算術級數的總和(它們的總和等於d + 2*d + 3*d + ...
)。
long multiplesSum(long N, long d) {
long highestMultiple = (N-1) / d * d;
long numberOfMultiples = highestMultiple / d;
return (d + highestMultiple) * numberOfMultiples / 2;
}
那么結果將等於:
long resultSum(long N) {
return multiplesSum(N, 3) + multiplesSum(N, 5) - multiplesSum(N, 3*5);
}
我們需要減去multiplesSum(N, 15)
因為有些數字是3
和5
倍數,所以我們將它們加了兩次。
復雜度: O(1)
在這種情況下,您無法降低時間復雜度,因為每組數字仍然有O(N)
。 但是,您可以使用整數除法來減少常數乘數 :
static int findMultiples(int N, int s)
{
int c = N / s, sum = 0;
for (int i = 0, k = s; i < c; i++, k += s)
sum += k;
return sum;
}
這樣,您只循環遍歷多個倍數而不是整個范圍[0,N]。
請注意,您將需要執行findMultiples(N, 3) + findMultiples(N, 5) - findMultiples(N, 15)
,以刪除3和5的重復倍數。因此,循環數為N / 3 + N / 5 + N / 15 = 0.6N,而不是N。
編輯:通常,任意數量的除數的解決方案是sum(findMultiples(N,divisor_i) - findMultiples(N,LCM(all_divisors))
;但是,只有sum(1/divisor_i) + 1/LCM(all_divisors) < 1
才值得這樣做sum(1/divisor_i) + 1/LCM(all_divisors) < 1
,否則將會有更多的循環,幸運的是,這對於2個除數永遠不會成立。
從1到(包括)N的所有數字的總和已知為N(N + 1)/ 2(無需迭代)。
因此,從K到KM的K的所有倍數之和是上述公式的K倍,得出KM(M + 1)/ 2。
將此與@meowgoesthedog的findMultiples(N,3)+ findMultiples(N,5)-findMultiples(N,15)的想法結合起來,您將獲得一個固定時間的解決方案。
解決問題的方法。解決問題的最快方法。
import java.util.*;
class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
while(t!=0)
{
long a=in.nextLong();
long q=a-1;
long aa=q/3;
long bb=q/5;
long cc=q/15;
long aaa=((aa*(aa+1))/2)*3;
long bbb=((bb*(bb+1))/2)*5;
long ccc=((cc*(cc+1))/2)*15;
System.out.println(aaa+bbb-ccc);
t-=1;}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.