A 使所有元素都可以被 3 整除的最少操作数
遍历 n u m s nums nums ,每有一个不被 3 3 3 整除的数,则操作数加 1 1 1
class Solution {
public:
int minimumOperations(vector<int>& nums) {
int res = 0;
for (auto x : nums)
if (x % 3 != 0)
res++;
return res;
}
};
B 使二进制数组全部等于 1 的最少操作次数 I
遍历:顺序遍历 n u m s nums nums 中的长为 3 3 3 的子数组,若子数组首元素为 0 0 0 ,则反转子数组,最终判断 n u m s nums nums 的最后两个元素是否为 1 1 1
class Solution {
public:
int minOperations(vector<int>& nums) {
int n = nums.size();
int res = 0;
for (int i = 0; i < n - 2; i++)
if (nums[i] == 0) {
res++;
nums[i + 1] ^= 1;
nums[i + 2] ^= 1;
}
if (nums[n - 2] == 0 || nums[n - 1] == 0)
return -1;
return res;
}
};
C 使二进制数组全部等于 1 的最少操作次数 II
遍历:顺序遍历 n u m s nums nums ,记录当前操作的总次数,对于每个遍历到的位置,若当前操作次数为偶数则当前位置的元素不变,否则当前位置元素反转
class Solution {
public:
int minOperations(vector<int>& nums) {
int res = 0;
for (auto x : nums)
if ((x + res) % 2 == 0)
res++;
return res;
}
};
D 统计逆序对的数目
动态规划:设 p [ i , j ] p[i,j] p[i,j] 为 i + 1 i+1 i+1 个不同的数形成的恰有 j j j 个逆序对的排列的数目(模 1 e 9 + 7 1e9+7 1e9+7),通过枚举排列的最后一个元素来进行状态转移,转移过程注意不满足题目条件的排列,可以通过记忆化搜索实现
class Solution {
public:
using ll = long long;
ll mod = 1e9 + 7;
int numberOfPermutations(int n, vector<vector<int>>& requirements) {
vector<int> cnt(n, -1);
for (auto& it : requirements)
cnt[it[0]] = it[1];//固定要求
vector<vector<ll>> p(n, vector<ll>(cnt[n - 1] + 1, INT64_MIN));
function<ll(int, int)> get = [&](int loc, int k) {//记忆化搜索
if (k < 0)
return 0LL;
if (p[loc][k] != INT64_MIN)
return p[loc][k];
if (cnt[loc] != -1 && cnt[loc] != k)//不满足要求
return p[loc][k] = 0;
if (loc == 0)
return p[loc][k] = k == 0 ? 1 : 0;
p[loc][k] = 0;
for (int i = 0; i <= loc; i++) {//枚举最后一位
p[loc][k] += get(loc - 1, k - (loc - i));
p[loc][k] %= mod;
}
return p[loc][k];
};
return (get(n - 1, cnt[n - 1]) + mod) % mod;
}
};