重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
记录 LeetCode 刷题中遇到的数学相关题目
创新互联专注于昭阳企业网站建设,响应式网站建设,成都做商城网站。昭阳网站建设公司,为昭阳等地区提供建站服务。全流程按需求定制开发,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务204. 计数质数质数是数论中很重要的一部分,应该也是大多数人刚接触数论时接触到第一个知识点。下面根据官方题解总结一下几种判断质数或者筛质数的方法:
下面是线性筛的做法:
public int countPrimes(int n) {Listprimes = new ArrayList(); //质数集合
int[] isPrime = new int[n]; //标记质数
Arrays.fill(isPrime, 1);
for (int i = 2; i< n; ++i) {if (isPrime[i] == 1) {primes.add(i);
}
//注意如果 i * primes.get(j) >= n 直接跳出循环
for (int j = 0; j< primes.size() && i * primes.get(j)< n; ++j) {isPrime[i * primes.get(j)] = 0;
//遇到能整除的质数结束标记过程
if (i % primes.get(j) == 0) {break;
}
}
}
return primes.size();
}
326. 3 的幂根据数据范围,n 不大于 231- 1 的大取值为 319= 1162261467,那么如果 n 是 3 的幂,即 n = 3x,那么一定满足 n * 3k= 319,其中 0<= k<= 19,亦即 319% n = 0,所以只需判断这个等式是否成立即可。还要判断 n 是否大于 0:
public boolean isPowerOfThree(int n) {return n >0 && 1162261467 % n == 0;
}
1262. 可被三整除的大和remain 数组中,remain[0] 记录被遍历过的元素中,被三除后余 0 的元素大和;remain[[1] 记录被三除后余 1 的元素大和;remain[2] 记录被三除后余 2 的元素大和。当把所有元素遍历完后,remain[0] 就是本题答案
public int maxSumDivThree(int[] nums) {int len = nums.length;
int[] remain = new int[3];
int a,b,c;
for(int i = 0; i< len; i++){a = remain[0] + nums[i];
b = remain[1] + nums[i];
c = remain[2] + nums[i];
remain[a % 3] = Math.max(remain[a % 3], a);
remain[b % 3] = Math.max(remain[b % 3], b);
remain[c % 3] = Math.max(remain[c % 3], c);
}
return remain[0];
}
171. Excel表列序号字符串转化为数字,相当于 26 进制转化为十进制。
但十进制中没有 0,‘A’ 对应的是 1 而不是 0,所以将字母转化为数字时还需要加一,即 字母 - ‘A’ + 1 而不是 字母 - ‘A’
public int titleToNumber(String columnTitle) {int len = columnTitle.length();
int ans = 0;
for(int i = 0; i< len; i++){ans = ans * 26 + (columnTitle.charAt(i) - 'A' + 1);
}
return ans;
}
168. Excel表列名称171 题的思路逆过来即可。一开始是没做 171 题先做了 168 题,对这个 “cn–” 语句不能理解。然后就先做了 171 题,171 中的 “columnTitle.charAt(i) - ‘A’ + 1” 还是挺好理解的
cn 每次减一后对 26 取余得到的就是 171 中 " columnTitle.charAt(i) - ‘A’ ",所以再加 ‘A’ 得到的就是对应位上的字母。以此类推,将所有字母使用 StringBuilder 连接起来。连接的顺序是从低位到高位, reverse 成高位到低位即可
public String convertToTitle(int cn) {StringBuilder sb = new StringBuilder();
while (cn >0) {cn--;
sb.append((char)(cn % 26 + 'A'));
cn /= 26;
}
return sb.reverse().toString();
}
292. Nim 游戏如果轮到我的时候剩下 0 个石头,那我必输;如果剩下 1 个,那我可以拿 1 个,轮到对面没有石头拿,对面必输;如果剩下 2 个,那我可以拿 2 个,轮到对面没有石头拿,对面必输;如果剩下 3 个,那我可以拿 3 个,轮到对面没有石头拿,对面必输;如果剩下 4 个,那我不管拿 1 个还是 2 个还是 3 个,剩下的石头对面都可以一次性拿完,再次轮到我没有石头拿,我必输;如果剩下 5 个,我可以只拿 1 个,剩下 4 个给对面,跟剩下 4 个给我一样,对面必输…可以发现规律,如果 n 取余 4 为 0,那么我必输
public boolean canWinNim(int n) {return n % 4 != 0;
}
470. 用 Rand7() 实现 Rand10()randX() 可以得到 [1,X],那么 randX() - 1 为 [0,X - 1],(randX() - 1) * Y 为 [0,(X - 1)Y],那么 (randX() - 1) * Y + randY() 即为 [1,X*Y]
故已有 randX(),randY(),可以通过 (randX() - 1) * Y + randY() 得到 randX*Y
所以对于这道题,一开始已有 rand7,可以得到 rand49,如果结果在 [1,40] 中,就可以取余 10 然后加 1 得到 rand10。如果结果在 [41,49],就可以减去 40,得到 [1,9],即 rand9,可以跟 rand7 得到 rand63。同理如果结果在 [1,60] 可以得到 rand10,否则就是得到 rand3,可以跟 rand7 得到 rand21。此时如果结果在 [1,20] 可以得到 rand10,否则只剩下 1 这一个结果,无法继续得到新的 rand,只能从头开始循环
public int rand10() {while(true) {int rand7_1 = rand7();
int rand7_2 = rand7();
int r1 = (rand7_1 - 1) * 7 + rand7_2; //rand 49
if(r1<= 40) return r1 % 10 + 1; //rand 10
r1 -= 40; //rand 9
int rand7_3 = rand7();
int r2 = (r1 - 1) * 7 + rand7_3; //rand 63
if(r2<= 60) return r2 % 10 + 1; //rand 10
r2 -= 10; //rand 3
int rand7_4 = rand7();
int r3 = (r2 - 1) * 7 + rand7_4; //rand 21
if(r3<= 20) return r3 % 10 + 1;
//此时r3 - 20是1,说明后续无法继续去找rand X*Y了,只能重新开始循环
}
}
50. Pow(x, n)计算 xn,如果是按照 n 个 x 相乘的思路,复杂度为 O(n);而快速幂基于分治的思想,xn会等于 xn/2的平方,因此可以先计算出 xn/2然后进行一次平方运算得到 xn,同理,xn/2又等于 xn/4,因此可以先计算出 xn/4然后进行一次平方运算得到 xn/2,以此类推,因此总的复杂度为 O(logn),从而减少运算时间
要注意的是,如果 n 为奇数,那么 xn应该等于 xn/2* xn/2* x,因此需要判断进行平方根的平方运算时需不需要多乘一个 x
class Solution {public double myPow(double x, int n) {return n >= 0 ? quickPow(x, n) : 1.0 / quickPow(x, -n);
}
public double quickPow(double x, long n) {if (n == 0) {return 1.0;
}
//计算平方根
double tmp = quickPow(x,n / 2);
return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;
}
}
剑指 Offer 62. 圆圈中最后剩下的数字约瑟夫环。参考题解。
我们知道最后剩下的数字在最后一个数组中下标肯定为 0,由于在上一轮要删除第 m 个数,而且不是最后剩下这个数,所以最后剩下这个数在上一轮,也就是倒数第二个数组中的前面一定有 m 个数,它才不会被删掉,所以它在倒数第二个数组中的下标就是 (0 + m) % 2,0 + m 表示前面有 m 个数,但由于前面不一定有 m 个数,所以我们要把数组看成循环数组,所以求下标时要取余数组大小,倒数第二个数组的大小为 2 ,所以取余 2。得到的就是最后剩下的这个数在倒数第二个数组中的下标,以此类推,推算到第一个数组,也即原数组,就能得到最后剩下的数字在原数组中的下标,从而找到这个数
public int lastRemaining(int n, int m) {int res = 0;
for(int i = 2;i<= n;i++){res = (res + m) % i;
}
return res;
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧