GitHub链接:https://github.com/WilliamWuLH/LeetCode
如果你觉得不错可以 ⭐Star 和 Fork ❤
15.3Sum
排序 + 双指针遍历:
首先,将给定的数组进行排序(从小到大的顺序)。
遍历排序后的数组中的每一个数,如果这个数之前已经讨论过了则可以跳过。
将取出的数作为“目标”,使用双指针在排序后的数组中找另外的两个数:
一个左指针指向该取出的数的后一个数,即此时的最低位。
另一个右指针指向数组的最后一个数,即此时的最高位。
由于数组已经是从小到大进行排序了,所有令此时的三个数的和为 sum:
- 如果 sum > 0,说明右指针指向的数太大,要向左移,即使得所指的数变小(如果向左移后的数和之前一样大则需要继续向左移);
- 如果 sum < 0,说明左指针指向的数太小,要向右移,即使得所指的数变大(如果向右移后的数和之前一样大则需要继续向右移);
- 如果 sum = 0,说明找到答案,并让左指针和右指针都向中间靠拢,看有没有新的答案。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int len = nums.size();
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
for(int i=0;i<len-2;i++){
if(i > 0 && nums[i-1] == nums[i])
continue;
int left = i+1,right = len-1;
while(left < right){
int sum = nums[i] + nums[left] + nums[right];
if(sum > 0)
while(left < --right && nums[right] == nums[right+1]);
else if(sum < 0)
while(++left < right && nums[left-1] == nums[left]);
else{
vector<int> temp = {nums[i],nums[left],nums[right]};
ans.push_back(temp);
while(++left < right && nums[left] == nums[left-1]);
while(left < --right && nums[right] == nums[right+1]);
}
}
}
return ans;
}
};
16.3Sum Closest
排序 + 双指针遍历:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int len = nums.size();
int ans = nums[0] + nums[1] + nums[2];
sort(nums.begin(),nums.end());
for(int i = 0; i < len-2; i++ ){
if( i > 0 && nums[i] == nums[i-1])
continue;
int left = i+1,right = len-1;
while(left < right){
int sum = nums[i] + nums[left] + nums[right];
if(abs(ans - target) > abs(sum - target))
ans = sum;
if(sum > target)
while(left < --right && nums[right] == nums[right+1]);
else if(sum < target)
while(++left < right && nums[left] == nums[left-1]);
else
return sum;
}
}
return ans;
}
};
18.4Sum
排序 + 双指针遍历:
类似 3Sum 那道题,都是一个套路,只是多了一层循环。
增加了几个判断可以提高程序性能:
- 如果此时最小的四个数相加还比目标数值大,那么可以直接跳出循环。
- 如果此时遍历的第 i 个数和最大的三个数相加还比目标数值小,那么可以直接进入下一轮循环(使得第 i 个数变大)。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
int len = nums.size();
sort(nums.begin(),nums.end());
for(int i=0;i<len-3;i++){
if(i > 0 && nums[i] == nums[i-1])
continue;
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target)
break;
if(nums[i]+nums[len-1]+nums[len-2]+nums[len-3] < target)
continue;
for(int j=i+1;j<len-2;j++){
if(j > i+1 && nums[j] == nums[j-1])
continue;
int left = j+1,right = len-1;
while(left < right){
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target)
while(left < --right && nums[right] == nums[right+1]);
else if(sum < target)
while(++left < right && nums[left] == nums[left-1]);
else{
ans.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
while(left < --right && nums[right] == nums[right+1]);
while(++left < right && nums[left] == nums[left-1]);
}
}
}
}
return ans;
}
};