题目一
思路
1、先读好题,把每个元素都乘以二,再把结果加入数组,则新的混合数组元素个数必是偶数个。
2、拿1和2举例子,在读入2的时候,需要快速知道1在不在数组里面,因为数据量极为庞大,且两个数可能相距很远,所以最快速的做法就是hash表。但是可能出现重复元素,所以要用unordered_map,key值是数组元素,value是出现次数。出现无法配对的元素先放在map里面,当出现次数归零,说明完全被匹配完了,所以该把它从map里删除。
3、这里我们拿1,3,4,2,6,8如果保持数组乱序,那么,小的数可能出现在数组后面,大的数在前面,更大的数在最前面,这样一定会产生匹配混乱的情况。每个数和乘二后的数按照递增顺序排列,每一个数对都按照这个顺序排列,最后把所有数对放在一起递增排列,比如1,2,3,4,6,8这样,就会发现,答案数组里的元素,一定会出现在其乘二后的元素之前,这样就不会产生错误匹配了,原来的元素和乘二的元素相对位置一前一后固定了,不会匹配出错的
代码
注:其实题目中特意强调随机打乱,说明数组中的数无规律了,这样尤其在匹配的时候最容易出错,相对位置不固定,所以最常见的方法就是排序重整数组,让相对位置固定就好了
class Solution {
public:
vector<int> findOriginalArray(vector<int>& changed) {
vector<int> ans;
unordered_map<int, int> mapper;
if (changed.size() % 2 != 0) {
//快速判断特殊情况
return ans;
}
sort(changed.begin(), changed.end());//排序,固定相对位置
for (int i = 0; i < changed.size(); i++) {
if (changed[i] % 2 != 0) {
//奇数元素一定是目标,所以直接加入
if (mapper.count(changed[i]) == 0) {
//第一次加入
mapper.insert(pair<int, int>(changed[i], 1));
}
else {
mapper[changed[i]]++;//多次加入
}
}
else {
int item = changed[i] / 2;//偶数元素要判断他是不是乘二元素,不是的话直接加入,因为他的乘二元素一定在后面
if (mapper.count(item) > 0) {
ans.push_back(item);
mapper[item]--;
if (mapper[item] == 0) {
//答案元素被匹配光了,删除
mapper.erase(item);
}
}
else {
//加入,原理同上
if (mapper.count(changed[i]) == 0) {
mapper.insert(pair<int, int>(changed[i], 1));
}
else {
mapper[changed[i]]++;
}
}
}
}
if (mapper.size() > 0) {
//如果map里有剩余元素,说明一定未完全匹配,为错
vector<int> tmp;
return tmp;
}
return ans;
}
};
(所有代码均已在力扣上运行无误)
经测试,该代码运行情况是(经过多次测试所得最短时间):
题目二:
思路
1、针对1到n-2这个范围中的每个元素,他的左面都小于他,右面都大于他,那么我们就记录一下他左面最大的人是谁,右面最小的的人是谁,它大于左面最大的,小于右面最小的,就满足了第一条,第二条略。
2、其实面对大数据量,很明显能想得到的就是hash表,其次在发现一个数组数据很乱很没有找规律的头绪的时候,可以尝试排序重整数组,让数组变得有序,或者前缀和,前缀最大,后缀最小等等技巧,多试一试,总有一个方法会弄出来的
代码
class Solution {
public:
int sumOfBeauties(vector<int>& nums) {
int ans = 0;
int max[100005];
int min[100005];
int n = nums.size();
max[0] = nums[0];
min[n - 1] = nums[n - 1];
for (int i = 1; i < n; i++) {
max[i] = nums[i] > max[i - 1] ? nums[i] : max[i - 1];//求前缀最大
}
for (int i = n - 2; i >= 0; i--) {
min[i] = nums[i] < min[i + 1] ? nums[i] : min[i + 1];//求后缀最小
}
for (int i = 1; i < n - 1; i++) {
//保证了每个元素在O(1)的复杂度内完成计算
if (nums[i] > max[i - 1] && nums[i] < min[i + 1]) {
ans += 2;
continue;
}
else if (nums[i - 1] < nums[i] && nums[i] < nums[i + 1]) {
ans += 1;
continue;
}
}
return ans;
}
};
(所有代码均已在力扣上运行无误)
经测试,该代码运行情况是(经过多次测试所得最短时间):
时间复杂度O(N)
空间复杂度O(N)
题目三
思路
直接模拟
代码
class Solution {
public:
int countKDifference(vector<int>& nums, int k) {
int ans = 0;
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (abs(nums[i] - nums[j]) == k) {
ans++;
}
}
}
return ans;
}
};
(所有代码均已在力扣上运行无误)
经测试,该代码运行情况是(经过多次测试所得最短时间):
时间复杂度O(N^2)
题目四
思路
计算带+和-的数目,相减就行
代码
class Solution {
public:
int finalValueAfterOperations(vector<string>& operations) {
int add = 0;
int sub = 0;
for (int i = 0; i < operations.size(); i++) {
for (int j = 0; j < 3; j++) {
//vector里面一个元素三个字符,检测+-
if (operations[i][j] == '-') {
sub++;
break;
}
else if (operations[i][j] == '+') {
add++;
break;
}
else {
continue;
}
}
}
return add - sub;
}
};
(所有代码均已在力扣上运行无误)
经测试,该代码运行情况是(经过多次测试所得最短时间):
时间复杂度O(N)