今天在做leetcode周赛算法题的时候有一道关于求因数的题,正常的算法和求结果都已经做到了,但是对于一个大数据量的测试案例却始终无法通过,也就是时间复杂度不满足要求。后面思考的时候发现了这一类的题都可以把时间复杂度从O(n)降到.在这里记录一下方法。
题目是这样的:https://leetcode-cn.com/problems/four-divisors/
这题的普通解法是:
1.遍历数组中的每一个数。
2.对于每个数字,求它的所有因数,符合要求的相加。其中暴力做法求所有余数这一步骤需要O(n)
但是这样的解法没办法满足时间复杂的要求。对于求因数的这一个步骤,我们可以使用一种时间复杂度为的算法。
即只从 1开始,遍历到为止,其中n是每一个要被求余数的数字。因为如果n可以被一个小于的因子a整除,那么这个数一定有一个因数是大于的,它的值为b = n/a.
这样,我们就可以很轻易的写出我们的算法:
class Solution {
public int sumFourDivisors(int[] nums) {
int result = 0;
for(int e : nums)
{
int temp = 0;
int cnt = 0;
for(int i = 1; i * i <= e; i++)
{
if(e % i == 0)
{
if(i * i == e)
{
cnt = 0;
break;
}
cnt += 2;
temp = temp + i + (e/i);
}
}
if(cnt == 4)
result += temp;
}
return result;
}
}
这个算法中还有一个巧妙的点在于,如何这个数是一个平方数,那么它的因数个数一定为奇数,不满足题目要求,可以直接排除。这个算法的时间复杂度是,其中n是数组长度,m是每一个数的大小。