Array[1] n sum 问题

本文深入探讨了解决编程难题的方法,包括使用哈希表优化时间复杂度,实现高效的两数之和查找;通过排序与双指针技巧解决三数之和问题并找到最接近目标和的组合;进一步讲解如何通过去重与双指针方法解决三数之和等于零的问题,并与最大水桶问题建立联系;最后,通过递进的逻辑与重复的元素处理策略,解答四数之和的求解方法。

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

1. Two Sum

由于要返回index+1, 用unordered_map存elem到index的映射,注意这样的testcase:[2,3,5], 4

<span style="font-size:14px;">class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        unordered_map<int, int> num2index;
        for (int i=0; i<numbers.size(); ++i) num2index[numbers[i]] = i;
        vector<int> rs;
        for (int i=0; i<numbers.size(); ++i) {
            int left = target - numbers[i];
            if (num2index.find(left) != num2index.end() && num2index[left] != i) {
                rs.push_back(i+1); rs.push_back(num2index[left]+1);
                break;
            }
        }
        return rs;
    }
    
};</span>


2. 3Sum Closest
要求返回最近的那个和。这个就可以先排序了,因为扫描的时间复杂度起码O(n^2)。

<span style="font-size:14px;">class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        int mini = INT_MAX;
        int rs = 0;
        sort(num.begin(), num.end());
        
        int n = num.size();
        for(int i=0; i<n-2; ++i) {
            for (int j=i+1, k=n-1; j<k;) {  //夹逼
                int now = num[i] + num[j] + num[k];
                int gap = abs(now-target);
                
                rs = gap < mini ? now : rs;  //注意这句和下句的顺序
                mini = gap < mini ? gap : mini;
                
                if (now > target) --k;
                else ++j;
            }
        }
        return rs;
    }
};</span>


3. 3Sum

要求返回所有和为0的结果。和上一题相比主要困难的地方在于去重, 都必须计算第一个出现的元素,后面重复的就continue过,而不能遇到最后一个不重的才计算。注意下面这种代码的写法和直接对num去重的区别!(去重去的是num[a]和num[a-1]的那些num[a],.., 而不是去掉这种num[a] = num[b] = num[c])此外注意当sum == 0的时候,++b和--c要同时进行。

注意,这里的夹逼法和Container With Most Water的联系!!

<span style="font-size:14px;">class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        vector<vector<int> > rs;
        sort(num.begin(), num.end());
        int n = num.size();
        for (int a=0; a<n-2; ++a) {
            if (a>0 && num[a-1] == num[a]) continue;
            for (int b=a+1, c=n-1; b<c;)
            {
                if (b > a+1 && num[b-1] == num[b]) {  //去重
                    ++b; continue;
                }
                if (c < n-1 && num[c+1] == num[c]) {  //去重
                    --c; continue;
                }
                int sum = num[a] + num[b] + num[c];
                if (sum == 0){
                    vector<int> tmp({num[a], num[b], num[c]});
                    rs.push_back(tmp);
                    ++b; --c;
                }
                else if (sum < 0)
                    ++b;
                else
                    --c;
            }
            
        }
        return rs;
    }
};</span>


4. 4Sum
和上面的3sum一模一样。
<span style="font-size:14px;">class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int>> rs;
        sort(num.begin(), num.end());
        int n = num.size();
        for(int a=0; a < n-3; a++) {
            if (a>0 && num[a] == num[a-1]) continue;
            for (int b=a+1; b < n - 2; ++b) {
                if (b > a+1 && num[b] == num[b-1]) continue;
                for (int c = b+1, d = n-1; c < d;) {
                    if (c > b+1 && num[c] == num[c-1]) {
                        ++c; continue;
                    }
                    if (d < n - 1 && num[d] == num[d+1]) {
                        --d; continue;
                    }
                    
                    int sum = num[a] + num[b] + num[c] + num[d];
                    if (sum == target)
                    {
                        vector<int> tmp({num[a], num[b], num[c], num[d]});
                        rs.push_back(tmp);
                        ++c; --d;
                    }
                    else if(sum < target) ++c;
                    else --d;
                }
            }
        }
        return rs;
    }
        
};</span>

大家有更简洁精炼的代码,一起讨论啊!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值