题目一
测试链接:1675. 数组的最小偏移量 - 力扣(LeetCode)
分析:可以观察出,如果元素是奇数,那么只有两种可能,即奇数本身和奇数乘2而偶数可以震荡。所以可以将奇数扩大两倍,偶数不变放入一个有序表,每次拿有序表的最大值减最小值,求得偏移量,然后将最大值除以2直到最大值为奇数退出循环,此时记录的偏移量就是最小偏移量。代码如下。
class Solution {
public:
int minimumDeviation(vector<int>& nums) {
int length = nums.size();
multiset<int> table;
for(int i = 0;i < length;++i){
if(nums[i] % 2 == 1){
table.insert(nums[i] * 2);
}else{
table.insert(nums[i]);
}
}
set<int>::iterator minValue, maxValue;
int ans = -((1 << 31) + 1);
int temp;
while (true)
{
minValue = table.begin();
maxValue = table.end();
--maxValue;
ans = min(ans, (*maxValue) - (*minValue));
if((*maxValue) % 2 == 1){
break;
}
temp = (*maxValue);
table.erase(maxValue);
table.insert(temp/2);
}
return ans;
}
};
题目二
测试链接:781. 森林中的兔子 - 力扣(LeetCode)
分析:对相同答案做词频统计,对每一个词频计算兔子的最少数量相加即是答案。代码如下。
class Solution {
public:
int numRabbits(vector<int>& answers) {
int length = answers.size();
unordered_map<int, int> table;
unordered_map<int, int>::iterator pos;
for(int i = 0;i < length;++i){
pos = table.find(answers[i]);
if(pos == table.end()){
table.insert(pair<int, int>(answers[i], 1));
}else{
++((*pos).second);
}
}
int ans = 0;
for(unordered_map<int, int>::iterator it = table.begin();it != table.end();++it){
ans += (((*it).second + (*it).first) / ((*it).first + 1)) * ((*it).first + 1);
}
return ans;
}
};
题目三
测试链接:2449. 使数组相似的最少操作次数 - 力扣(LeetCode)
分析:注意到操作并不会改变数字的奇偶性,所以可以将nums数组和target数组中的奇数和偶数分组,并且nums数组中的奇数个数等于target数组中的奇数个数,nums数组中的偶数个数等于target数组中的偶数个数,并且对这四个数组进行从小到大排序。奇数数组中相同下标即是对应的变换,偶数数组也是一样,将所有变换的差值相加除以一次变换可以弥补的差值4就是答案。代码如下。
class Solution {
public:
long long makeSimilar(vector<int>& nums, vector<int>& target) {
vector<int> nums_odd;
vector<int> nums_even;
vector<int> target_odd;
vector<int> target_even;
for(int i = 0;i < nums.size();++i){
if(nums[i] % 2 == 1){
nums_odd.push_back(nums[i]);
}else{
nums_even.push_back(nums[i]);
}
}
for(int i = 0;i < target.size();++i){
if(target[i] % 2 == 1){
target_odd.push_back(target[i]);
}else{
target_even.push_back(target[i]);
}
}
sort(nums_odd.begin(), nums_odd.end());
sort(nums_even.begin(), nums_even.end());
sort(target_odd.begin(), target_odd.end());
sort(target_even.begin(), target_even.end());
long long ans = 0;
for(int i = 0;i < nums_odd.size();++i){
ans += abs(nums_odd[i] - target_odd[i]);
}
for(int i = 0;i < nums_even.size();++i){
ans += abs(nums_even[i] - target_even[i]);
}
return ans / 4;
}
};
题目四
测试链接:知识竞赛_牛客题霸_牛客网
分析:可以看出,x和y是否除以2对于中间过程并不影响,所以可以先求出答案之后再除以2。首先对员工进行排序,按员工推理能力值减阅读能力值的绝对值从小到大进行排序。遍历到某一员工时,如果当前员工推理值较小,则加上之前员工中最大的推理值;如果当前员工阅读值较小,则加上之前员工中最大的阅读值,更新答案,最后返回时,答案除以2。代码如下。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n;
struct Worker
{
int ai;
int bi;
};
int main(void){
scanf("%d", &n);
vector<Worker> worker;
worker.reserve(n);
for(int i = 0;i < n;++i){
Worker temp;
scanf("%d%d", &temp.ai, &temp.bi);
worker.push_back(temp);
}
sort(worker.begin(), worker.end(), [](Worker& w1, Worker& w2){
return abs(w1.ai - w1.bi) < abs(w2.ai - w2.bi);
});
int ans = 0;
int max_ai = 0;
int max_bi = 0;
Worker w;
for(int i = 0;i < n;++i){
w = worker[i];
if(w.ai > w.bi){
ans = max(ans, w.bi + max_bi);
}else{
ans = max(ans, w.ai + max_ai);
}
max_ai = max(max_ai, w.ai);
max_bi = max(max_bi, w.bi);
}
printf("%.1f", (float)ans / 2);
return 0;
}
题目五
测试链接:871. 最低加油次数 - 力扣(LeetCode)
分析:用一个大根堆维护可以加油的加油站,当当前无法到达终点时,加油量最大的那个加油站,如果还是无法到达终点更新可以加油的加油站,加油量最大的加油站,循环往复。代码如下。
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
if(startFuel >= target){
return 0;
}
if((stations.size() == 0 && startFuel <= target) || startFuel < stations[0][0]){
return -1;
}
int length = stations.size();
auto cmp = [](int& a, int& b){
return a < b;
};
priority_queue<int, vector<int>, decltype(cmp)> p(cmp);
int index = 0;
for(;index < length;++index){
if(stations[index][0] <= startFuel){
p.push(stations[index][1]);
}else{
break;
}
}
int ans = 0;
while (!p.empty())
{
startFuel += p.top();
++ans;
p.pop();
if(startFuel >= target){
break;
}
for(;index < length;++index){
if(stations[index][0] <= startFuel){
p.push(stations[index][1]);
}else{
break;
}
}
}
return startFuel >= target ? ans : -1;
}
};