[Algo] 贪心策略3
1. 最小区间
// 1. 最小区间
// https://leetcode.cn/problems/smallest-range-covering-elements-from-k-lists/
class Node {
public:
int v; // 值
int i; // 来自数组i
int j; // 来自数组i下标j
Node(int x, int y, int z) : v(x), i(y), j(z) {}
};
vector<int> smallestRange(vector<vector<int>>& nums) {
int k = nums.size();
auto comparator = [](const Node &a, const Node &b) {
return a.v != b.v ? (a.v < b.v) : (a.i < b.i);
};
set<Node, decltype(comparator)> orderedTable(comparator);
for (int i = 0; i < k; i++) {
orderedTable.insert(Node(nums[i][0], i, 0));
}
int begin, end, len = INT32_MAX;
while (orderedTable.size() == k) {
Node min = *orderedTable.begin(), max = *orderedTable.rbegin();
if (max.v - min.v < len) {
begin = min.v;
end = max.v;
len = max.v - min.v;
}
orderedTable.erase(orderedTable.begin());
if (min.j + 1 < nums[min.i].size()) {
orderedTable.insert(Node(nums[min.i][min.j + 1], min.i, min.j + 1));
}
}
vector<int> ans = {begin, end};
return ans;
}
2. 数组的最小偏移量
// 2. 数组的最小偏移量
// https://leetcode.cn/problems/minimize-deviation-in-array/description/
int minimumDeviation(vector<int>& nums) {
set<int> orderedMap;
for (auto &num : nums) {
if (num & 1) orderedMap.insert(2 * num);
else orderedMap.insert(num);
}
int min = *orderedMap.begin(), max = *orderedMap.rbegin(), ans = max - min;
while (ans > 0 && (max & 1) == 0) {
orderedMap.erase(max);
orderedMap.insert(max / 2);
max = *orderedMap.rbegin();
min = *orderedMap.begin();
ans = max - min < ans ? max - min : ans;
}
return ans;
}
3. 森林中的兔子
// 3. 森林中的兔子
// https://leetcode.cn/problems/rabbits-in-forest/
int numRabbits(vector<int>& answers) {
vector<int> arr(1000);
for (auto &answer : answers) {
arr[answer]++;
}
int ans = 0;
for (int i = 0; i < 1000; i++) {
int group = (arr[i] + i) / (i + 1);
ans += group * (i + 1);
}
return ans;
}
4. 使数组相似的最少操作次数
// 4. 使数组相似的最少操作次数
// https://leetcode.cn/problems/minimum-number-of-operations-to-make-arrays-similar/
void partitionAndSortOddEven(vector<int>& nums) {
if (nums.empty()) return;
auto it_first_even = partition(nums.begin(), nums.end(), [](int n) {
return (n & 1);
});
sort(nums.begin(), it_first_even);
sort(it_first_even, nums.end());
}
long long makeSimilar(vector<int>& nums, vector<int>& target) {
partitionAndSortOddEven(nums);
partitionAndSortOddEven(target);
long long diff = 0;
for (int i = 0; i < nums.size(); i++) {
diff += abs(nums[i] - target[i]);
}
return diff / 4;
}
5. 最低加油次数
// 5. 最低加油次数
// https://leetcode.cn/problems/minimum-number-of-refueling-stops/description/
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
if (target <= startFuel) return 0;
vector<int> lastStation = {target, 0};
stations.push_back(lastStation);
int n = stations.size(), totalFuel = startFuel, cnt = 0;
priority_queue<int, vector<int>, less<int>> maxHeap;
for (auto &station : stations) {
int curPos = station[0], curFuel = station[1];
while (totalFuel < curPos && !maxHeap.empty()) {
cnt++;
totalFuel += maxHeap.top();
maxHeap.pop();
}
if (totalFuel < curPos) return -1;
maxHeap.push(curFuel);
}
return cnt;
}