Q1 找出缺失和重复的数字
-
解题思路:
- 用哈希表记录grid中各数字分别出现了多少次
- 遍历[1, n* n]的范围,找到出现两次和缺失的数字
-
解题代码:
class Solution {
public:
vector<int> findMissingAndRepeatedValues(vector<vector<int>>& grid) {
int n = grid.size();
unordered_map<int, int> um;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
um[grid[i][j]] += 1;
}
}
vector<int> ans(2, 0);
for (int i = 1; i <= n*n; i++) {
if (um[i] == 2) {
ans[0] = i;
}
if (um[i] == 0) {
ans[1] = i;
}
}
return ans;
}
};
Q2 划分数组并满足最大差限制
-
解题思路:
- 将数组从小到大进行排序
- 每三个元素分成一个数组,检查是否满足最大元素 - 最小元素 <= k,如不满足,返回空数组
-
解题代码:
class Solution {
public:
vector<vector<int>> divideArray(vector<int>& nums, int k) {
int n = nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
for (int i = 2; i < n; i += 3) {
if (nums[i] - nums[i-2] > k) {
return {};
}
vector<int> temp{nums[i-2], nums[i-1], nums[i]};
ans.push_back(temp);
}
return ans;
}
};
Q3 使数组成为等数数组的最小代价
-
解题思路:
- 首先预处理所有的回文数
- 要将所有数字变成同一个回文数,应该变成与原数组中位数相距最近的回文数(中位数贪心)
- 使用前缀和计算将所有数变成目标数需要的代价
-
解题代码:
vector<int> ns;
int init = []() {
for (int i = 0; i <= 9; i++) {
ns.push_back(i);
}
for (int i = 1; i <= 9999; i++) {
for (int j = 0; j <= 9; j++) {
int temp = i, num = i;
num = num * 10 + j;
while (temp != 0) {
num = num * 10 + temp % 10;
temp /= 10;
}
ns.push_back(num);
}
int temp = i, num = i;
while (temp != 0) {
num = num * 10 + temp % 10;
temp /= 10;
}
ns.push_back(num);
}
ns.push_back(1e9 + 1);
sort(ns.begin(), ns.end());
return 0;
}();
class Solution {
public:
long long minimumCost(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<long long> s(n+1, 0);
for (int i = 1; i <= n; i++) {
s[i] = s[i-1] + nums[i-1];
}
int target = nums[(n-1)/2];
int idx = lower_bound(ns.begin(), ns.end(), target) - ns.begin(); // 大于等于中位数的第一个数
auto func = [&](long long num) -> long long {
int idx = lower_bound(nums.begin(), nums.end(), num) - nums.begin();
long long res = num * idx - (s[idx]) + s[n] - s[idx] - num * (n-idx);
return res;
};
return min(func(ns[idx]), func(ns[idx-1]));
}
};
Q4 执行操作使频率分数最大
- 题目链接
- 解题思路:
- 对数组进行排序
- 找一个最长的子数组,可以在k次操作内将子数组内所有数字都变成该子数组的中位数
- 滑动窗口 + 前缀和 + 中位数贪心
- 解题代码:
class Solution {
public:
int maxFrequencyScore(vector<int>& nums, long long k) {
sort(nums.begin(), nums.end());
int n = nums.size();
vector<long long> s(n+1, 0);
for (int i = 1; i <= n; i++) {
s[i] = s[i-1] + nums[i-1];
}
auto cal = [&](int left, int right) -> long long {
int target = left + (right - left) / 2;
long long temp = nums[target];
long long res = temp * (target - left) - s[target] + s[left] + s[right+1] - s[target] - temp * (right - target + 1);
return res;
};
int ans = 1;
int left = 0, right = 0;
while (right < n) {
while (cal(left, right) > k) {
left += 1;
}
ans = max(ans, right - left + 1);
right += 1;
}
return ans;
}
};