灵神算法基础算法精讲[01] :
两数之和 三数之和【基础算法精讲 01】_哔哩哔哩_bilibili
167.两数之和 II - 输入有序数组
链接 :
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路 :
- 采用双指针的思想,因为给出的数组是有序的,n = len(numbers),定 l = 0,r = n-1;
- 如果s = numbers[l] + numbers[r] > target , 那么s要变小,则r--;
- 如果s = numbers[l] + numbers[r] < target , 那么s要变大,则l++;
- 如果s = numbers[l] + numbers[r] = target , 那么就得到结果了,则返回[l+1,r+1]即可;
代码(python):
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
l = 0
r = len(numbers)-1
while True:
s = numbers[l] + numbers[r]
if s==target:
break
if s>target:
r -= 1
else :
l += 1
return [l+1,r+1]
代码(c++):
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int l=0,r=numbers.size()-1;
while(true){
int s = numbers[l]+numbers[r];
if(s==target) break;
if(s>target) r--;
else l++;
}
return {l+1,r+1};
}
};
三数之和
链接 :
三数之和
思路 :
假设满足条件的三个数的下标分别为i , j, k,且默认i<j<k;
先对数组进行排序,方便后面的操作
对i进行枚举,然后就是一个双指针的问题,令x=nums[i] , j=i+1 , k=n-1 ; 令 s = x + nums[j] + nums[k] , 剩下的就可以参考前一题中的思路:
1.如果s > 0 : k--;
2.如果s<0 : j++
3.如果s=0 : 添加到结果中;
去重 : 分别对i,j,k去重;
优化 : 如果相邻的三数之和>0,那么就可以直接break了,因为后面的只会加大
如果nums[i]+nums[n-1]+nums[n-2]<0,那么就continue,因为这是以i为起点的情况下s的最大值,如果小于0,那么直接continue,跳到下一个 i 上;
代码( python ):
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
# 排序
# i<j<k
ans = []
n = len(nums)
for i in range(n-2):
x = nums[i]
if i>0 and x==nums[i-1]:# 对x去重
continue
if x+nums[i+1]+nums[i+2]>0: # 优化
break
if x+nums[-2]+nums[-1]<0: # 优化
continue
j = i + 1
k = n - 1
while j < k:
s = x + nums[j] + nums[k]
if s>0:
k -= 1
elif s < 0:
j += 1
else:
ans.append([x,nums[j],nums[k]])
j += 1
while j<k and nums[j]==nums[j-1]:# 对j去重
j+=1
k-=1
while j<k and nums[k]==nums[k+1]:# 对k去重
k-=1
return ans
代码( c++ ) :
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
for(int i=0;i<n-2;i++)
{
int x = nums[i];
if(x+nums[i+1]+nums[i+2] > 0) return ans;//如果三数和最小值大于0,那么直接返回
if(x+nums[n-1]+nums[n-2]<0) continue;
// 对a去重
if(i>0 && nums[i] == nums[i-1]) continue;
int left = i+1;
int right = n-1;
while(right>left)
{
int x = nums[i] + nums[left] + nums[right];
if(x > 0) right--;
else if(x < 0) left++;
else
{
ans.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 ++;
left++;
right--;
}
}
}
return ans;
}
};