开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
[6193. 沙漏的最大总和]
nm = 150150 约等于2w多个数据 因此可以枚举下每一种情况的7个位置,计算一下总和,然后更新最大值, 并且这里的所有数都是非负数 ->答案非负数!
先枚举参考点!! -> 可以设中心点为我们的参考点 中心点的行范围是:[1,数组行数-2] 列范围是:[1,数组列数-2]
然后计算以(i,j)为中心的参考点的沙漏型的总和
累加沙漏中的元素的和
class Solution {
public:
int maxSum(vector<vector<int>>& grid) {
int row = grid.size();//行
int col = grid[0].size();//列
int ans = 0;
for(int i = 1;i<row-1;i++)
{
for(int j = 1;j<col-1;j++)
{
//(i,j)就是沙漏的中心点
//计算当前以(i,j)为中心点的沙漏的和
int sum = grid[i][j];
for(int k = j-1;k<=j+1;k++)
{
sum += grid[i-1][k] + grid[i+1][k];
}
//更新答案
ans = max(ans,sum);
}
}
return ans;
}
};
[6194. 最小 XOR]
1)因为数据范围是10^9 二进制表示最多有30位, 2^30 >= 10亿
2)首先要求一下num2里面二进制1的数量,这样就直到答案x里面1的数量
3)由于异或可以看成是:无进位相加, 所以我们可以发现:
- 如果num1这一位本来是1,我们把x的1放到这一位,那么会让num1减去一个数
- 如果num1这一位本来是0,我们把x的1放到这一位,那么会让num1加上一个数
如果这一位越高,加的数/减的数越大, 现在放的1的数量是唯一确定的(等于num2的置位数),假设为k, 要求放了k个1之后,使num1的结果最小
贪心:
x的置位数和num2的置位数相同,意味着x的二进制序列中有k个 1,我们需要合理的分配这k个1,为了让异或和最小,这些1应当从高位到低位匹配 num中的 1, 如果匹配完num1中所有的1,还有多余的1可以分配,那么就从低位到高位把0改为1 (加上2^比特位所在的位置)
- 先从高位选择1,后从低位选择0
- 首先统计num2二进制中1出现的个数, 将这些1分配出去, 因为是要得到一个最小的 x^num1, 所以我们需要对num1的二进制位的权值进行排序, 使用贪心思想尽可能地找到最小的 x^num1, 如此就可以找出x了.
res = a^x ==> x = a^res
class Solution {
public:
int minimizeXor(int num1, int num2) {
int cnt = 0;
//1.计算num2中比特位1的个数(置位数)
while(num2)
{
num2&=(num2-1);
cnt++;
}
//求法2 while(num2) cnt+= b&1,b>>=1;
int res = 0;
//先从高位往低位选择置1,要保证还有1可以置
for(int i = 29;i>=0 && cnt>0;i--)
{
if((num1 >> i)&1)//这一位是1
{
res -= (1<<i);
cnt--;
}
}
//从低位往高位置1,要保证还有1可以置
for(int i = 0;i<30&&cnt>0;i++)
{
if(((num1 >> i)&1) == 0)//这一位是0
{
res += (1<<i);
cnt--;
}
}
//其中num1+res就是x^num1异或的答案ans 如何得到x呢? x = ans^num1
return (num1+res)^num1;
}
};
x 最低位上的 1 变为 0 : x = x&(x-1)
x 最低位上的 0 变为 1: x = x | (x+1)