Leetcode421周赛 (Mod处理)
第一题思路没错,但做太久了。第二题做完快没时间了,选了第二题类似的第四做(结果最后几个样例过不了, 第三题结束之后发现更加简单一点。本周很多题都是涉及到MoD处理。
第一题
简单来说就是分别求lcm和gcd的前缀和,后缀和,其它思路和除本身以外的乘积一样。
class Solution {
public long maxScore(int[] nums) {
if(nums.length == 0)return 0;
if(nums.length == 1)return (long)nums[0]*nums[0];
long[] gcd_1 = new long[nums.length];
long[] gcd_2 = new long[nums.length];
long[] lcm_1 = new long[nums.length];
long[] lcm_2 = new long[nums.length];
gcd_1[0] = nums[0];
lcm_1[0] = nums[0];
gcd_2[nums.length-1] = nums[nums.length-1];
lcm_2[nums.length-1] = nums[nums.length-1];
for(int i = 1;i<nums.length;i++){
gcd_1[i] = gcd(gcd_1[i-1], nums[i]);
lcm_1[i] = lcm(lcm_1[i-1], nums[i]);
}
for(int i = nums.length-2;i>=0;i--){
gcd_2[i] = gcd(gcd_2[i+1], nums[i]);
lcm_2[i] = lcm(lcm_2[i+1], nums[i]);
}
long[] max = new long[nums.length];
long ans = 0;
for(int i=0;i<nums.length;i++){
if(i==0){
ans = Math.max(ans , gcd_2[1] * lcm_2[1]);
}else if(i==nums.length-1){
ans = Math.max(ans , gcd_1[nums.length-2] * lcm_1[nums.length-2]);
}else{
ans = Math.max(gcd(gcd_1[i-1] , gcd_2[i+1]) * lcm(lcm_1[i-1], lcm_2[i+1]), ans);
}
}
return Math.max(gcd_1[nums.length-1]*lcm_1[nums.length-1] , ans);
}
long gcd(long a , long b){
while(b!=0){
long tmp = b;
b = a % b;
a =tmp;
}
return a;
}
long lcm(long a, long b){
return (a/gcd(a,b))*b;
}
}
第二题
这题刚开始写的模拟思路,即每次更改之后将字符串修改,再次迭代,超时。最后模拟将字符串抽象成26位数组,逐次迭代, 时间复杂度 26*N
class Solution {
static final int MOD = 1000000007;
public int lengthAfterTransformations(String s, int t) {
long count = 0;
long[] index = new long[26];
for(char c: s.toCharArray()){
index[c-'a']++;
}
for(int i=0;i<t;i++){
long tmp = index[25];
for(int x=25;x>0;x--){
index[x] = index[x-1];
}
index[0] = tmp;
index[1] = (index[1] + tmp) % MOD;
}
for(int i=0;i<26;i++){
count = (count + index[i] ) % MOD;
}
return (int)count;
}
}
第三题
记忆化搜索,从数组最后一位开始,seq1和seq2 可以同时不选当前位,或者seq1选, 或者seq2选
class Solution {
int[] nums;
private static final int MOD = 1_000_000_007;
int[][][] memo;
public int subsequencePairCount(int[] nums) {
this.nums = nums;
Arrays.sort(nums);
memo = new int[nums.length+2][nums[nums.length-1]+2][nums[nums.length-1]+2];
for(int[][] mem : memo){
for(int[] me:mem){
Arrays.fill(me, -1);
}
}
return (dfs(nums.length - 1, 0, 0) - 1 + MOD) % MOD;
}
int dfs(int index, int seq1, int seq2){
if(index<0) return seq1==seq2?1:0;
if(memo[index][seq1][seq2]!=-1)return memo[index][seq1][seq2];
int num = nums[index];
long res = (long) dfs(index-1, seq1, seq2) +
dfs(index - 1, gcd(num, seq1), seq2) +
dfs(index -1, seq1, gcd(num, seq2));
return memo[index][seq1][seq2] = (int) (res % MOD);
}
int gcd(int a , int b){
while(b!=0){
int tmp = b;
b = a % b;
a = tmp;
}
return a;
}
}
常用MOD方式
一般来说Mod都是10^9 + 7
// 定义:
static final int MOD = 1000000007;
// ans += dfs()
ans = ( ans + dfs()) % MOD
// int --> long --> int
long res = (long) dfs()
ans = (int) (res % MOD)
// - 1 防止溢出 ( dfs() -1 ) % MOD
ans = (dfs() - 1 + MOD) % MOD