两数之和 & 三数之和

19 篇文章 0 订阅
18 篇文章 0 订阅

1、描述 两数之和=target_输出下标

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:

输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
链接

思路
双指针,+ 二分

# 解法一:双指针
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int>res;
        int i = 0;
        int j = numbers.size() - 1;
        while(i < j) {
            if(numbers[i] + numbers[j] == target) {
                return {i + 1, j + 1};
            } else if(numbers[i] + numbers[j] < target) {
                i++;
            } else{
                j--;
            }
        }
        return {0, 0};

    }
};

# 解法二:双指针 + 二分
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int>res;
        int i = 0;
        int j = numbers.size() - 1;
        while(i < j) {
            int mid = i + (j - i) / 2;
            if(numbers[i] + numbers[mid] > target) { // 这里>target ,直接把左边的区间排除了。
                j = mid - 1;
            } else if(numbers[j] + numbers[mid] < target) {
                i = mid + 1;
            } else if(numbers[i] + numbers[j] > target) {
                j--;
            } else if(numbers[i] + numbers[j] < target) {
                i++;
            } else{
                return {i + 1, j + 1};
            }
        }
        return {0, 0};

    }
};

2、三数之和=0

15给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组

来源:力扣(LeetCode)
链接:

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例
给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

2、思路
1、排个序,把数组重复的元素删除,(错误想法,因为直接删除就会删除-1,-1,2这种答案序列),3层循环暴力求解
2、从左边循环固定一个,然后双指针遍历剩下的

3、notes
1、sort(v.begin(),v.end());
2、双指针的循环体写法用while
3、花括号表示一个数据集

v.push_back({10,20,30});
1
4、内层while(j<k&&)不写会有如下错

Line 924: Char 34: runtime error: addition of unsigned offset to 0x602000000590 overflowed to 0x60200000058c (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_vector.h:933:34

4、复杂度
时间:O(n平方)
空间:排序的时候sort()函数,O(logN)
如果不能原数组排序,拷贝一个新的,就是O(N)

5、code
ac

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n=nums.size();      
        vector<vector<int>> ve;
        //if(n<3) return ve;       
        int i,j,k;
        sort(nums.begin(),nums.end());//排序   
        for(i=0;i<n-2 && nums[i]<=0;i++)
        {
            //if(nums[i]==nums[i+1]) continue;  // 如果这么写的话,[-1,-1,2],这种情况就排除了
            if (i > 0 && nums[i] == nums[i - 1]) continue; // 从后往前, (i > 0)防止越界
            j=i+1;
            k=n-1;
            while(j<k && nums[k]>=0)  // =0 是为了{0,0,0}  // 双指针的标准循环
                {
                    if(nums[i]+nums[j]+nums[k]==0)
                    {                   
                        ve.push_back({nums[i],nums[j],nums[k]});
                        //while(nums[i]==nums[i+1]) i++;
                        while(j<k && nums[j]==nums[j+1]) j++;  // j<k 此半句很重要
                        while(j<k && nums[k]==nums[k-1]) k--;
                        j++,k--;  // 逗号,这么写  // 同时别忘了写这句话
                    }
                    else if(nums[i]+nums[j]+nums[k]<0)
                    {
                        j++;
                    }
                    else
                    k--;
                }           
        }
        return ve;
    }
};


WA


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n=nums.size();
        
        vector<vector<int>> ve;
        if(n<3) return ve;
        vector<int> v11;
        int i,j,k;
        sort(nums.begin(),nums.end());//排序
        /* vector<int> v;  //如果这么更新数组则会把 {-1,-1 ,2}给错过
        int t=nums[0];
        j=0;
        v.push_back(t);
        for(i=1;i<n;i++)
        {
            if(nums[i]==v[j])
            continue;
            v.push_back(nums[i]);
            j++;
        }
        n=v.size(); */

        for(i=0;i<n-2&&nums[i]<=0;i++)
        {
            for(j=i+1;j<n-1;j++)
            {
                for(k=n-1;k<j;k--)
                {
                    if(nums[i]+nums[j]+nums[k]==0)
                    {
                        //v11.erase(v11.begin(),v11.end());
                        //v11.push_back(v[i]);
                        //v11.push_back(v[j]);
                        //v11.push_back(v[k]);
                        ve.push_back({nums[i],nums[j],nums[k]});
                        while(nums[i]==nums[j]) i++;
                        while(nums[k]==nums[k-1]) k--;
                    }
                    else if(nums[i]+nums[j]+nums[k]<0)
                    {
                        j++;
                    }
                    else
                    k--;

                }
            }
        }
        return ve;
    }
};


  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值