leetcode 1|167.two sum 1|2 && 3.three sum && 16.3Sum Closest && 18. 4Sum

本文解析了从两数之和到四数之和的算法实现,包括不同场景下的解决方案,如数组已排序或未排序的情况,并介绍了如何利用数据结构如哈希表和多级映射来提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. two sum

下面有c++ 和Python代码


Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,

return [0, 1].


由于一样的元素只能用一次,涉及查找,map肯定是最快的。map<int,int>存下标

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
{
	     map<int,int> index;
        index[nums[0]] = 1;
        for(int i = 1; i < nums.size() ;i++)
        {
            int key = target - nums[i];
            if (index.find(key) != index.end())
            {
                vector<int> ret(1, index[key]);
                ret.push_back(i + 1);
                return ret;
            }
            else
                index[nums[i]] = i + 1;
        }
    }
};

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        d = {}
        d[nums[0]] = 0
        size = 1
        while size < len(nums):
            if target - nums[size] in d:
                ret = [d[target - nums[size]], size]
                return ret
            if not nums[size] in d:
                d[nums[size]] = size
            size += 1


167. Two Sum II - Input array is sorted


Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

两个指针往中间移动,这种找出两个数的这种题应该想到两个指针!!

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
       vector<int> ret;
       int left = 0;
       int right = nums.size() - 1;
       while (left < right)
       {
            if (nums[left] + nums[right] == target)
            {
                ret.push_back(left+1);
                ret.push_back(right+1);
                return ret;
            }
            else if (nums[left] + nums[right] < target)
                left++;
            else 
                right--;
       }
    }
};


3. three SUM

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
解题思路:先排序,大的在后面,固定首个数字,然后 两个指针往中间移动 ,确定剩下两个数字。


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        sort(nums.begin(), nums.end());
        int target, left, right;
        vector<vector<int>> result;
        if (nums.size() == 0)
            return result;
        vector<int> m1;
        for (int i = 0; i < nums.size() - 2; i ++)
        {
            target = -nums[i];
            if (nums[i] > 0)  //因为后面的都是更大的数,直接不用再找了
                break;
            if (i > 0 && nums[i] == nums[i-1])  //减少重复查找
                continue;
            left = i + 1;
            right = nums.size() - 1;
            while (left < right)
            {
                if (nums[left] + nums[right] == target)
                {
                    m1.push_back(nums[i]);
                    m1.push_back(nums[left]);
                    m1.push_back(nums[right]);
                    result.push_back(m1);
                    if (result[result.size()-1] == result[result.size()-2]) //去除重复
                        result.erase(result.end());      
                    m1.clear();
                    right --;
                    left ++;
                }
                else if (nums[left] + nums[right] > target)
                    right --;
                else
                    left ++;
            }
        }
        return result;
    }
};


16. 3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
    For example, given array S = {-1 2 1 -4}, and target = 1.
    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

 题目:3sum最接近target   
 思路:和3sum一样,先排序,固定第一个数,两个指针移动后两个数,往中间移动。

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target)
    {
        if (nums.size() == 0)
            return 0;
        int targ;
        int result = 0;
        int small = INT_MAX;
        sort(nums.begin(), nums.end());
        int left, right;
        for (int i = 0;i < nums.size() - 2; i++)
        {
            targ = target - nums[i];
            left = i + 1;
            right = nums.size() - 1;
            while (left < right)
            {
                if (abs(nums[left] + nums[right] - targ) < small)
                { 
                    small = abs(nums[left] + nums[right] - targ);
                    result = nums[left] + nums[right] + nums[i];
                }
                
                if (nums[left] + nums[right] > targ)
                    right --;
                else if (nums[left] + nums[right] < targ)
                    left ++;
                else
                    return target;      
            }
        }
        return result;
    }
};


18. 4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

way-1:两重for固定两个数,两个指针移动确定后两个数

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target)
    {
        //way-1
        
        vector<vector<int>> result;
        if (nums.size() < 4)
            return result;
        vector<int> m1;
        sort(nums.begin(), nums.end());
        int left, right;
        for (int i = 0; i < nums.size() - 3; i++)
        {
            if (i > 0 && nums[i] == nums[i-1])
                continue;
            for (int j = i + 1; j < nums.size() - 2; j++)
            {
                if (j > i + 1 && nums[j] == nums[j-1])
                    continue;
                left = j + 1;
                right = nums.size() - 1;
                while (left < right)
                {
                    if (nums[i]+nums[j]+nums[left]+nums[right] > target)
                        right --;
                    else if (nums[i]+nums[j]+nums[left]+nums[right] < target)
                        left ++;
                    else
                    {
                        m1.push_back(nums[i]);
                        m1.push_back(nums[j]);
                        m1.push_back(nums[left]);
                        m1.push_back(nums[right]);
                        if(result.empty() || (result.size() > 0 && m1 != result[result.size()-1]))
                             result.push_back(m1);
                        m1.clear();
                        right --;
                        left ++;
                    }
                }
            }
        }
        return result;
    }
};

way-2:先对给定数组做初始化,把所有两两值的和求出来,我们就把求4Sum变为求2Sum了,注意初始化的时候求两两和值也要保存两个数字的下标,题中我用的是multimap <int, pair < int, int > >,因为可能会有重复的所以要用multimap, multimap第一个int是表示和值,第二个pair是两个数的下标,而且用multimap我们默认是排序的,刚好初始化完直接用首和尾指针查找满足2Sum为0的数可以了。下标我们都记录着,所以很容易得到原先的4个值。找到4个值后我们把它保存在set中,这样也满足题意的要求返回值是有序的。


        vector<vector<int>> ret;
        if (nums.size() < 4)
            return ret;
        else if (nums.size() == 4)
        {
            if (accumulate(nums.begin(), nums.end(), 0) == target)
            {
                ret.push_back(nums);
                return ret;
            }
        }
        
        multimap<int,pair<int,int>> mm;
        for (int i = 0; i < nums.size(); i++)
            for (int j = i + 1;j < nums.size(); j++)
                mm.insert({nums[i] + nums[j], {i,j}});  //注意map中有pair的插入方式!
        
        for (auto i = mm.begin(); i != mm.end(); i++)
        {
            int x = target - i->first;
            auto range = mm.equal_range(x);  //  multimap.equal_range(key)使用一定要会!
            for(auto j = range.first; j != range.second; j++)  //range.second指向最后一个查询结果的下一位置,有点像迭代器的end()
            {
                int a = i->second.first;
                int b = i->second.second;
                int c = j->second.first;
                int d = j->second.second;
                if(a!=b && a!=c && a!=d && b!=c && b!=d && c!=d)
                {
                    vector<int> m1 = {nums[a], nums[b], nums[c], nums[d]};
                    sort(m1.begin(), m1.end());
                    ret.push_back(m1);
                }
            }
        }
        sort(ret.begin(), ret.end());
        ret.erase(unique(ret.begin(), ret.end()), ret.end());
        return ret;








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值