持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
6192. 公因子的数目
给你两个正整数 a 和 b ,返回 a 和 b 的 公 因子的数目。
如果 x 可以同时整除 a 和 b ,则认为 x 是 a 和 b 的一个 公因子 。
示例 1:
输入: a = 12, b = 6
输出: 4
解释: 12 和 6 的公因子是 1、2、3、6 。
示例 2:
输入: a = 25, b = 30
输出: 2
解释: 25 和 30 的公因子是 1、5 。
提示:
1 <= a, b <= 1000
思路
范围不大,直接枚举
代码
class Solution {
public:
int commonFactors(int a, int b) {
int ans = 0;
for(int i = 1; i <= min(a, b); i ++) {
if (a % i == 0 && b % i == 0) ans ++;
}
return ans;
}
};
6193. 沙漏的最大总和
给你一个大小为 m x n 的整数矩阵 grid 。
按以下形式将矩阵的一部分定义为一个 沙漏 :
返回沙漏中元素的 最大 总和。
注意: 沙漏无法旋转且必须整个包含在矩阵中。
示例 1:
输入: grid = [[6,2,1,3],[4,2,1,5],[9,2,8,7],[4,1,2,9]]
输出: 30
解释: 上图中的单元格表示元素总和最大的沙漏:6 + 2 + 1 + 2 + 9 + 2 + 8 = 30 。
示例 2:
输入: grid = [[1,2,3],[4,5,6],[7,8,9]]
输出: 35
解释: 上图中的单元格表示元素总和最大的沙漏:1 + 2 + 3 + 5 + 7 + 8 + 9 = 35 。
提示:
m == grid.lengthn == grid[i].length3 <= m, n <= 1500 <= grid[i][j] <= 106
思路
直接for 循环遍历每一个可以形成沙漏的形状即可
代码
class Solution {
public:
int maxSum(vector<vector<int>>& grid) {
int ans = 0;
int n = grid.size();
int m = grid.back().size();
pair<int, int> fa[] = {
{0, 0},
{-1, 0}, {-1, -1}, {-1, 1},
{1, 0}, {1, -1}, {1, 1}
};
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
int res = 0, f = 1;
for (auto v : fa) {
int x = i + v.first;
int y = j + v.second;
if (x < 0 || y < 0 || x >= n || y >= m) {
f = 0;
break;
}
res += grid[x][y];
}
if (!f) continue;
ans = max(ans, res);
}
}
return ans;
}
};
6194. 最小 XOR
给你两个正整数 num1 和 num2 ,找出满足下述条件的整数 x :
x的置位数和num2相同,且x XOR num1的值 最小
注意 XOR 是按位异或运算。
返回整数 **x 。题目保证,对于生成的测试用例, x 是 唯一确定 的。
整数的 置位数 是其二进制表示中 1 的数目。
示例 1:
输入: num1 = 3, num2 = 5
输出: 3
解释:
num1 和 num2 的二进制表示分别是 0011 和 0101 。
整数 3 的置位数与 num2 相同,且 3 XOR 3 = 0 是最小的。
示例 2:
输入: num1 = 1, num2 = 12
输出: 3
解释:
num1 和 num2 的二进制表示分别是 0001 和 1100 。
整数 3 的置位数与 num2 相同,且 3 XOR 1 = 2 是最小的。
提示:
1 <= num1, num2 <= 109
思路
要求异或值最小 且 1的个数和num2相同
首先,我们从大到小去构造一个数,他1的位置和num1一样 这样可以保证异或最小
其次,若是num2的1的个数比num1多,那么我们从低位到高位再依次补齐即可
代码
class Solution {
public:
int minimizeXor(int num1, int num2) {
int cnt = 0;
for (int i = 0; i < 31; i ++) cnt += (num2>>i&1);
int ans = 0;
for (int i = 30; i >= 0 && cnt; i --) {
if (num1 >> i & 1) {
ans |= 1 << i;
cnt --;
}
}
for (int i = 0; i < 31 && cnt; i ++) {
if (ans >> i & 1) continue;
cnt --;
ans |= 1 << i;
}
return ans;
}
};
6195. 对字母串可执行的最大删除数
给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以:
- 删除 整个字符串
s,或者 - 对于满足
1 <= i <= s.length / 2的任意i,如果s中的 前i个字母和接下来的i个字母 相等 ,删除 前i个字母。
例如,如果 s = "ababc" ,那么在一步操作中,你可以删除 s 的前两个字母得到 "abc" ,因为 s 的前两个字母和接下来的两个字母都等于 "ab" 。
返回删除 s 所需的最大操作数。
示例 1:
输入: s = "abcabcdabc"
输出: 2
解释:
- 删除前 3 个字母("abc"),因为它们和接下来 3 个字母相等。现在,s = "abcdabc"。
- 删除全部字母。
一共用了 2 步操作,所以返回 2 。可以证明 2 是所需的最大操作数。
注意,在第二步操作中无法再次删除 "abc" ,因为 "abc" 的下一次出现并不是位于接下来的 3 个字母。
示例 2:
输入: s = "aaabaab"
输出: 4
解释:
- 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "aabaab"。
- 删除前 3 个字母("aab"),因为它们和接下来 3 个字母相等。现在,s = "aab"。
- 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "ab"。
- 删除全部字母。
一共用了 4 步操作,所以返回 4 。可以证明 4 是所需的最大操作数。
示例 3:
输入: s = "aaaaa"
输出: 5
解释: 在每一步操作中,都可以仅删除 s 的第一个字母。
提示:
1 <= s.length <= 4000s仅由小写英文字母组成
思路
想法:类似于kmp
我们得先求出来当前值的最大前缀和后缀相等是多少
这样求有什么好处呢
若是当前值的最大前缀和后缀加起来刚好不多不少,中间没有其他数组偏移
那么,我们就可以知道这个值是可以删除的
这个是第一点
其次,我们得贪心的删除,为保证删除次数最大,我们每次一个尽可能的删除掉最大的一串
因为若是删除小的,后续可能用的时候就不能够用了
比如 aabaab, 我们可以删除a, 或者 aab, 我们发现,删除 a之和,结果不会变得更好
时间复杂度:总体最多循环 n 次,每次求kmp数组的时间复杂度是 n,计算最大删除时间复杂度是n
总体下来,时间复杂度是
可以通过
代码
class Solution {
public:
int deleteString(string s) {
int ans = 0;
while (1) {
string p = " " + s;
vector<int> ne(p.size() + 2);
int m = s.size();
for (int i = 2, j = 0; i <= m; i ++ ) {
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j ++ ;
ne[i] = j;
}
int f = 0;
for (int i = m; i >= 1; i --) {
if (ne[i] * 2 == i) {
s = s.substr(ne[i]);
f = 1;
break;
}
}
ans ++;
if (f) continue;
break;
}
return ans;
}
};