9. 2815. 数组中的最大数对和(简单)
2815. 数组中的最大数对和 - 力扣(LeetCode)
思想
1.给你一个下标从 0 开始的整数数组 nums
。请你从 nums
中找出和 最大 的一对数,且这两个数数位上最大的数字相等。
返回最大和,如果不存在满足题意的数字对,返回 -1
。
2.根据条件"这两个数数位上最大的数字相等"即可枚举右,维护左,键为数数位上最大的数字,再根据"和 最大 的一对数",所以值为之前最大数的下标
代码
c++:
class Solution {
public:
int getMax(int a) {
int res = 0;
while (a) {
res = max(res, a % 10);
a /= 10;
}
return res;
}
int maxSum(vector<int>& nums) {
int n = nums.size(), res = -1;
map<int, int> mp; // 数位最大数字-最大数字下标
for (int j = 0; j < n; ++j) {
int t = getMax(nums[j]);
auto it = mp.find(t);
if (it != mp.end()) {
res = max(res, nums[j] + nums[it->second]);
if (nums[j] > nums[it->second])
mp[t] = j;
} else
mp[t] = j;
}
return res;
}
};
10. 2342.数位和相等数对的最大和(中等)
2342. 数位和相等数对的最大和 - 力扣(LeetCode)
思想
1.给你一个下标从 0 开始的数组 nums
,数组中的元素都是 正 整数。请你选出两个下标 i
和 j
(i != j
),且 nums[i]
的数位和 与 nums[j]
的数位和相等。
请你找出所有满足条件的下标 i
和 j
,找出并返回 nums[i] + nums[j]
可以得到的 最大值 。如果不存在这样的下标对,返回 -1。
2.跟2815. 数组中的最大数对和类似,只不过把条件"这两个数数位上最大的数字相等"改成"且 nums[i]
的数位和 与 nums[j]
的数位和相等"
代码
c++:
class Solution {
public:
int getSum(int a) {
int sum = 0;
while (a) {
sum += a % 10;
a /= 10;
}
return sum;
}
int maximumSum(vector<int>& nums) {
int n = nums.size(), res = -1;
map<int, int> mp;
for (int j = 0; j < n; ++j) {
int t = getSum(nums[j]);
auto it = mp.find(t);
if (it != mp.end()) {
res = max(res, nums[j] + nums[it->second]);
if (nums[j] > nums[it->second])
mp[t] = j;
} else
mp[t] = j;
}
return res;
}
};
11. 1679.K和数对的最大数目(中等,学习)
1679. K 和数对的最大数目 - 力扣(LeetCode)
思想
1.给你一个整数数组 nums
和一个整数 k
。
每一步操作中,你需要从数组中选出和为 k
的两个整数,并将它们移出数组。
返回你可以对数组执行的最大操作数。
2.条件"和为 k
的两个整数"说明可以枚举右,维护左,而"将它们移出数组"则说明要记录当前有几个值为k-nums[j]
的下标,所以值为下标个数,无需记录下标到底是多少
3.而我原来想存储下标集也是可行的,用vector<int>
,判断不为空,然后pop_back
删除最后一个元素(一开始忘记了这个)
代码
c++:
class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
int n = nums.size(), res = 0;
map<int, int> mp; // 和-下标个数
for (int j = 0; j < n; ++j) {
auto it = mp.find(k - nums[j]);
if (it != mp.end() && it->second) {
++res;
--it->second;
} else
++mp[nums[j]]; // 不能写++it->second,因为可能it->second无效
}
return res;
}
};
存储下标集:
class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
int n = nums.size(), res = 0;
map<int, vector<int>> mp; // 和-下标集
for (int j = 0; j < n; ++j) {
auto it = mp.find(k - nums[j]);
if (it != mp.end() && !it->second.empty()) {
++res;
it->second.pop_back(); // 用pop_back()
} else
mp[nums[j]].emplace_back(
j); // 不能写it->second.emplace_back(j),因为可能it->second无效
}
return res;
}
};
12. 面试题 16.24. 数对和(中等)
思想
1.设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
2.跟11. 1679.K和数对的最大数目一摸一样,只有记录下标次数即可
代码
c++:
class Solution {
public:
vector<vector<int>> pairSums(vector<int>& nums, int target) {
int n = nums.size();
vector<vector<int>> res;
map<int, int> mp; // 值-下标次数
for (int j = 0; j < n; ++j) {
auto it = mp.find(target - nums[j]);
if (it != mp.end() && it->second) {
res.push_back({target - nums[j], nums[j]});
--it->second;
} else
++mp[nums[j]];
}
return res;
}
};
13. 3371.识别数组中的最大异常值(中等)
3371. 识别数组中的最大异常值 - 力扣(LeetCode)
思想
1.给你一个整数数组 nums
。该数组包含 n
个元素,其中 恰好 有 n - 2
个元素是 特殊数字 。剩下的 两个 元素中,一个是所有 特殊数字 的 和 ,另一个是 异常值 。
异常值 的定义是:既不是原始特殊数字之一,也不是所有特殊数字的和。
注意 ,特殊数字、和 以及 异常值 的下标必须 不同 ,但可以共享 相同 的值。
返回 nums
中可能的 最大 异常值。
2.根据题意可以分析出2*nums[i]+nums[j]=sum
,其中nums[i]
是特殊数字,而nums[j]
是异常值,所以可以枚举一个,但这里不是枚举右,维护左,因为i和j的关系不定,不存在只考虑左边的数,所以一开始让所有数先进map,然后考虑枚举异常值还是特殊数字,发现枚举异常值更简单,"注意,特殊数字、和 以及 异常值 的下标必须 不同,但可以共享 相同的值。"所以找到的异常值有两种情况满足:(1)异常值与特殊值不同(2)值出现次数>1(可以不用写相同)
代码
c++:
class Solution {
public:
int getLargestOutlier(vector<int>& nums) {
int n = nums.size(), sum = 0, res = INT_MIN;
map<int, int> mp; // 值-次数
for (const int& x : nums) {
sum += x;
++mp[x];
}
// 2*nums[i]+nums[j]=sum,枚举特殊数字
for (int i = 0; i < n; ++i) {
auto it = mp.find(sum - 2 * nums[i]); // 找异常值
// 异常值存在,且(异常值与特殊值不同)或(异常值与特殊值相同且这个值至少出现两次)
if (it != mp.end() && (it->first != nums[i] ||
it->second > 1) )
res = max(res, it->first);
}
return res;
}
};