t1 存在连续三个奇数的数组
签到题,直接O(n²)遍历就能过。
class Solution { public: bool threeConsecutiveOdds(vector<int>& arr) { const int n = arr.size(); if(n < 3) return false; for(int i = 2; i < n; i++) { int cnt = 0; for(int j = i-2; j <= i; j++) { if(arr[j] % 2 != 0 || arr[j] == 1) cnt++; if(cnt == 3) return true; } } return false; } };
t2 使数组中所有元素相等的最小操作数
找规律贪心的题。给你一个数组,数组中每个元素i的值等于2*i+1(就是一个奇数序列)。每次操作可以选一个元素++再选一个元素–,问最少用多少次操作可以把整个序列的值化等。
不难发现,对于一个有序奇数列,最简单的方法就是以中位元素为分界线,右边的元素每次操作-1,左边的元素每次操作+1。根据这个策略分类讨论直接计算次数就行了。
class Solution { public: int minOperations(int n) { if(n % 2) { int ans = 0; int mid = n / 2; for(int i = 1; i <= mid; i++) ans += i * 2; return ans; } else { int ans = 0; int mid = n / 2; for(int i = 1; i <= mid; i++) ans += (i * 2) - 1; return ans; } } };
t3 两球之间的磁力
题目要求是求“最大的最小磁力”,那么可以考虑枚举磁力f。
思考一下不难得知,最小的磁力一定来自于相邻的两个球。所以,对于每个磁力f,确定它符合“任意两个相邻的球的距离都≥f”的条件,统计出所有f中最大的那一个即可。
考虑到数据范围,直接枚举绝对会超时,所以用二分,枚举关键字是距离,初始状态下left=0,right=INF=1e9。
class Solution { public: const int INF = 1e9 + 5; bool check(int f, vector<int>& p, int m, int n) { int lastPos = p[0];m--; for(int i = 1; i < n && m > 0; i++) { if(p[i] - lastPos >= f) { m--; lastPos = p[i]; } } return m <= 0; } int maxDistance(vector<int>& position, int m) { sort(position.begin(), position.end()); int left = 0, right = INF, ans = 0; const int n = position.size(); while(left <= right) { int mid = left + (right - left) / 2; if(check(mid, position, m, n)) { ans = max(ans, mid); left = mid + 1; } else right = mid - 1; } return ans; } };
赛时遇到这题懵了好一阵,下来学习到了这类“最小的最大/最大的最小”一般都是二分答案的题,也算是背个板子吧。
t4 吃掉 N 个橘子的最少天数
这是一道hard,又是一道dp。
每次操作有三种选择
- 吃一个橘子
- 如果剩下的橘子能被2整除,吃½的橘子。
- 如果剩下的橘子能被三整除,吃⅔的橘子
那么就存在很明显的状态转移关系,但是这题跟经典的dp不太一样,因为它的n范围足足有2e9,直接裸来肯定是要爆空间的。
这道题的状态分布十分离散(我也不知道为什么…参考坑神的实况视频原话),所以用map来贪空间,每次用find查询状态,可以节省很多空间。
关于这三种操作,显然可以得知,在能够进行操作2、3的情况下绝对不会优先进行操作1,这是一个贪心的思想,那么操作1就与2、3绑定起来了,转移时也只需要考虑操作2、3。
状态转移方程是:
dp[n] = min(dfs(n/2) + 1 + (n % 2), dfs(n/3) + 1 + (n % 3));
方程中dfs(n/2)很好理解,调用n/2这个状态的值,”+1″是算上“吃一半苹果”这个操作本身占用的一个次数,(n%2)是计算“通过操作1将橘子数调整到能被2整除”这个操作消耗的次数,如果它本身能被2整除这个数就是0,反之为1。方程的后半截结构同上。
有了方程这题的代码就十分简单了。
class Solution { public: map<int, int> dp; int ans(int n) { if(n == 1) return 1; if(n == 2 || n == 3) return 2; if(dp.find(n) != dp.end()) return dp[n]; dp[n] = min(ans(n/2) + 1 + (n % 2), ans(n/3) + 1 + (n % 3)); return dp[n]; } int minDays(int n) { dp.clear(); return ans(n); } };
评论
还没有任何评论,你来说两句吧!