5185. 存在连续三个奇数的数组
关键词:循环,判断奇偶 从 i = 2 开始枚举,检查 arr[i-2], arr[i-1], arr[i] 是否均为奇数。
class Solution {
public:
bool threeConsecutiveOdds(vector<int>& arr) {
for(int i = 2; i < arr.size(); i++) {
if(arr[i]%2 == 1 && arr[i-1]%2 == 1 && arr[i-2]%2 == 1) {
return true;
}
}
return false;
}
};
5488. 使数组中所有元素相等的最小操作数
关键词:找规律,计数 数组 arr 满足 arr[i] = (2 * i) + 1 ( 0 <= i < n )。 其所有元素的累加和为 ((2*1+1)+(2*n+1))*n/2,化简后为 (n+2)*n。 有累加和可知,操作完成后,每个元素均为 n+2。 操作前,arr 中总共有 x 个元素小于 n+2,。 这 x 个元素的累加和为。 操作后,前 x 个元素的累加和为 。 因为每次操作,小于 n+2 的元素的累加和会增加一,所以两和作差即为答案,。
class Solution {
public:
int minOperations(int n) {
return n*n/4;
}
};
5489. 两球之间的磁力
关键词:二分,贪心 换个题目的描述方式,向 n 个筐中放入m个球,使距离最近的一对球的距离最远。 划重点,一般题目中出现最近最远,最小最大,应该就是在考察二分/三分了。 可用二分算法求解的题目必须具备单调性:如果阈值 x 有解,那么所有小于 x 的阈值均有解。如果阈值 y 没有解,那么所有大约 y 的阈值均没有解。 尝试证明下这道题的单调性:
- 如果存在一种放置方案,满足任意一对球的距离不小于阈值 x。那么所有小于 x 的阈值,都可以用该方案应对。
- 如果对于阈值 x,不存在放置方案,那么对于所有大于 x 的阈值,显然都是无法满足的。(比如,一共10个位置,要放3个球,平均占地3.333个位置。你非要球均占地4个,臣妾做不到啊)。
既然满足单调性,直接套上二分模板,然后运用贪心算法,检查是否存在方案满足阈值 mid 即可。
class Solution {
public:
bool check(const vector<int> &pos, int m, int limit) {
for(int pre = -limit, i = 0; i < pos.size(); i++) {
if(pos[i] - pre >= limit) {
pre = pos[i];
m -= 1;
if(m == 0) {
return true;
}
}
}
return false;
}
int maxDistance(vector<int>& position, int m) {
sort(position.begin(), position.end());
int L = 0;
int R = 1000000000;
while(L <= R) {
int mid = (L+R)/2;
if(check(position, m, mid)) {
L = mid+1;
} else {
R = mid-1;
}
}
return L-1;
}
};
5490. 吃掉 N 个橘子的最少天数
关键词:DFS,贪心,记忆化 题目中给出了三种策略:
- 策略一:吃掉一个橘子。
- 策略二:如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。
- 策略三:如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。
最直接的思路就是暴力搜索:
但是这样暴力,即使用上记忆化,也要计算 n 个子问题。既然太慢了,那就尝试优化一下。 观察一下上述式子,可以发现是只使用策略一导致了较多的计算量,而且当 N 较大时,只使用策略一显然不是最优解。
- 只使用策略一需要 N 天。
- 只使用一次策略二和多次策略一需要 N%2 + 1 + (N%2)/2 天。
- N%2:先用N%2 次策略一,将 N 变为可被 2 整除。
- 1 : 使用 1 次策略二。
- (N%2)/2:还剩这些橘子,继续使用 (N%2) /2 次策略一。
- 只使用一次策略三和多次策略一需要 N%3 + 1 + N/3天。
显然当 N >= 3 时,后两种组合方案比第一种仅使用策略一的方案更优。 后两种组合方案,哪个更优呢?不知道哪个更有鸭,只好都算一下然后取较小值咯,反正计算量也很小了~
总结一下:
当 N <= 2 时,f(n) = n。 当 N > 2 时有:
class Solution {
public:
unordered_map<int, int> mark;
int f(int n) {
if(n <= 1) {
return n;
}
auto it = mark.find(n);
if(it != mark.end()) {
return it->second;
}
return mark[n] = min(f(n/2) + n%2, f(n/3) + n%3) + 1;
}
int minDays(int n) {
return f(n);
}
};