2022.4.13 参加了华为笔试,三道算法题, 个人感觉题目有点难
第一题:硬件资源的最佳分配
第二题:工单的分配策略
第三题:分糖果
第一题,题目看着都头疼,直接放弃了;
第二题,勉强把题目读懂了,堆了一部分代码,然后后面没思路了,感觉是用动态规划或贪心来做;
第三题,虽然读懂了题目,但最后也是没做出来。
不出意外的话,应该是挂了,没办法,自己太菜怪不得别人。
总结原因的话:
其一,主要还是算法逻辑训练不够,思维不够开阔
其二,对这种应用性较强的题目训练较少,一般这种题目很长,且题目不好理解,需要一定耐心
其三,平时刷题习惯于力扣的核心代码模式,对acm模式了解甚少,第一次用acm模式非常不习惯
由于第三题题目较短,能完整地回忆下来,而且就这样我也不太甘心,所以打算把第三题复盘一下,以下是我复盘的结果。
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
// 回溯:找到数组中的子数组,使子数组和为原数组的一半
void backtrace(vector<int>& nums, vector<int>& res, vector<int>& combine, int target, int startIdx, int sum) {
if (sum == target) {
res.resize(combine.size());
copy(combine.begin(), combine.end(), res.begin());
return;
}
for (int i = startIdx; i < nums.size() && sum + nums[i] <= target; i++) {
sum += nums[i];
combine.push_back(nums[i]);
backtrace(nums, res, combine, target, i + 1, sum);
combine.pop_back();
sum -= nums[i];
}
}
//分析:要求将一个数组分为两个子数组,子数组和皆为原数组和的一半
int main()
{
// input:
int n; // 糖果的袋数
cin >> n;
vector<int> nums(n); // 每袋糖果中,糖果的数量
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
// 逻辑代码:
int sum = 0;
int maxNum = nums[0];
for (int num : nums) {
sum += num;
maxNum = max(maxNum, num);
}
int target = sum / 2;
if (sum & 1 || maxNum > target) {
cout << -1 << endl;
exit(0);
}
sort(nums.begin(), nums.end());
vector<int> res; // 记录平分到的各袋糖果数量
vector<int> combine;
backtrace(nums, res, combine, target, 0, 0); // 利用回溯得到res, 即其中一人分得的各袋糖果数量
if (res.size() == 0) { // 没有分得糖果,即平分失败,输出-1
cout << -1 << endl;
exit(0);
}
vector<int> res2(nums.size() - res.size());
set_difference(nums.begin(), nums.end(), res.begin(), res.end(), res2.begin()); // res2 = nums-res得到剩下的各袋糖果
// output:
cout << "平分的糖果数量:" << target << endl;
cout << "小张分到的各袋糖果数:";
for (int num : res) {
cout << num << " ";
}
cout << '\n' << "小王分到的各袋糖果数:";
for (int num : res2) {
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}