454.四数相加II (题目链接:力扣)
思路:首先想到的就是暴力,直接四个for循环(用ordered_map记录重复的元素及其出现的次数,来简单优化一下)没想到还是超时了,后来就拆开来,用两个两层for循环(推荐以后凡是碰到多个数组,但是每个数组长度不是太大都可以这么做)。
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> map;
for(int a : nums1){
for(int b : nums2){
map[a+b]++;
}
}
int cnt = 0;
for(int c : nums3){
for(int d : nums4){
if(map.find(0 - (c + d)) != map.end()){
cnt += map[0 - (c + d)];
}
}
}
return cnt;
}
383. 赎金信(题目链接:力扣)
思路:和前两天的题目不能说毫不相关,只能说大差不差,直接自定义数组模拟哈希表来比较两个数组的元素是否相等就行了。
bool canConstruct(string ransomNote, string magazine) {
int ch[26] = {};
for(int i=0; i<magazine.size(); i++){
ch[magazine[i] - 'a']++;
}
for(int i=0; i<ransomNote.size(); i++){
if(--ch[ransomNote[i] - 'a'] < 0){
return false;
}
}
return true;
}
15. 三数之和 (题目链接:力扣)
思路:百思不得解,看来卡哥的解析才会做的,原来是用双指针的做法(这样相当于省去了一层for循环,降低时间复杂度),做之前先将原数组排好序。要注意的是每次在内部查找和外部查找都要去重,因为题目要求不能有重复的元素(要是题目允许只要下标不同就不用做任何去重)。
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
int size = nums.size();
for(int i=0; i<size-2; i++){
if(nums[i] > 0 ){
return result;
}
if(i>0 && nums[i] == nums[i-1]) continue;
int left = i + 1;
int right = size - 1;
while(left < right){
while(left < right && nums[i] + nums[left] + nums[right] > 0) right--;
while(left < right && nums[i] + nums[left] + nums[right] < 0) left++;
if(left >= right) break;
if(nums[i] + nums[left] + nums[right] == 0){
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
while(left < right && nums[right] == nums[right - 1]) right--;
while(left < right && nums[left] == nums[left + 1]) left++;
right--;
left++;
}
}
}
return result;
}
18. 四数之和 (题目链接:力扣)
思路:这题比上题又增加了一些难度,我之前理解比较吃力的地方就是第二层循环中的去重,相当于四元组的第二个元素的遍历,想通后其实和最外层循环一样,每个元素我只在相同的地方判断一次(但是后面元素和前面元素是可以相同的,所以必须先找了一次后再判断去重,如果说先去重了就会导致后面元素一定和前面元素不相同)。还有两个要注意的点就是long类型的转换来避免暂时的整数相加溢出、判断target的值不能光看到第一个元素大于它就break(负数的话是会相反的)。
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> result;
int size = nums.size();
if(size < 4) return result;
for(int i=0; i<size-3; i++){
if(nums[i] > target && nums[i] >= 0) return result;
if(i > 0 && nums[i] == nums[i-1]) continue;
for(int j=i+1; j<size-2; j++){
if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break;
if(j > i+1 && nums[j] == nums[j-1]) continue;
int left = j+1;
int right = size-1;
while(left < right){
while(left < right && (long) nums[i] + nums[j] + nums[left] + nums[right] > target) right--;
while(left < right && (long) nums[i] + nums[j] + nums[left] + nums[right] < target) left++;
if(left >= right) break;
if(nums[i] + nums[j] + nums[left] + nums[right] == target){
result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]});
while(left < right && nums[right] == nums[right - 1]) right--;
while(left < right && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return result;
}