two sum / three sum

一:TWO SUM,

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, 15, 11], target = 9,

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

思路:如果之前做过 Contiguous Array 题目,那么这个题目很容易。遍历数组,使用 ordered_map 数据结构(在 Contiguous Array 中已经说明过为什么使用 ordered_map 比 map更快了),保存每个元素期望配对的值 ( target - nums[i] ),以及对应的下标 i .判断当前的值,是否保存在 ordered_map 数据结构中,如果存在,则返回解。

 

//该方法总的时间复杂度是 O(n),目前在LeetCode中击败了 %99.98 码友

vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> mp;
        for(int i = 0;i<nums.size(); ++i)
        {
           if(mp.find(nums[i])!=mp.end()){    //在数据不超过千万级别的情况下,.find 时间复杂度是 O(1)
               int idx = mp[nums[i]];
               return {idx,i};
           }else{    //保存 target - num[i] 的值到map
               int value = target - nums[i];
               mp[value] = i;
           }
        }
        return {};
    }

 

拓展,如果不是结果返回下标,而是直接返回数组的值,还有什么解法?  可以首先给数组sort排序,耗时 O(nlogn);然后通过最前下标b,末尾下标e;如果nums[b] + nums[e] > target ,那么 --e;如果 nums[b] + nums[e] < target , 那么 ++b;相等则返回值。在 3 sum的问题上,由于需要处理重复的值,所以不宜再采用ordered_map方法。采用先排序后处理的方式更加简便。

 

二:THREE SUM,

Given an array nums of n integers, are there elements abc in nums 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.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

思路,2sum问题,是3sum问题的一个子问题。对于nums[i],转嫁为求在 [ i+1,nums.size() ) 区间的 2sum = (target - nums[i]) 的2sum问题。同理,3sum也是4sum的一个子问题。该方法时间复杂度O(n^2)

vector<vector<int>> threeSum(vector<int>& nums){
        int target = 0;
        vector<vector<int>> rlt;
        sort(nums.begin(),nums.end());
        for(int i=0;i<(int)nums.size() - 2;++i)  //注意啦,size_t(0) - 2 会提升为无符号数!
        {
            //特别注意需要去除重复,注意不要搞成了 if (nums[i] == nums[i+1]),nums[i]都没有机会在求解区域就被过滤掉了!
            if(i>0 && nums[i] == nums[i-1])   
                continue;
            if(nums[i] + nums[i+1] + nums[i+2] > target)
                return rlt;
            //问题缩小为,求nums在 [i+1, nums.size()) 区间的 2sum问题
            int ts = target - nums[i];
            int b = i+1;
            int e = nums.size() - 1;
            while(b<e)
            {
                if(nums[b]+nums[e] > ts)
                    --e;
                else if(nums[b]+nums[e] < ts)
                    ++b;
                else{
                    rlt.push_back(vector<int>{nums[i],nums[b],nums[e]});
                    //注意可能有多个重复的值,需要去除
                    while((b < e) && (nums[b +1] == nums[b])) ++b;
                    while((b < e) && (nums[e -1] == nums[e])) --e;
                    ++b; --e;
                }
            }
        }
        return rlt;
    }

 

### ABC384F Double Sum 2 Problem Explanation and Solution The **Double Sum 2** problem involves calculating a specific sum based on the elements of an array. The goal is to compute two sums: 1. \( S_1 \): The sum of all pairs \( (a_i + a_j)^2 \) where \( i < j \). 2. \( S_2 \): The sum of all triples \( (a_i + a_j + a_k)^2 \) where \( i < j < k \). To solve this efficiently without iterating over every possible pair or triple, one can use mathematical properties and precomputation techniques. #### Efficient Calculation Using Precomputed Values Let's denote: - \( n \) as the length of the input array. - \( A \) as the input array containing integers. Firstly, calculate several intermediate values that will help in computing both \( S_1 \) and \( S_2 \): ```python def double_sum_2(A): n = len(A) # Calculate prefix sums total_sum = sum(A) square_sum = sum(x * x for x in A) # Compute S1 using formula derived from expanding (ai + aj)^2 s1 = ((n - 1) * square_sum + 2 * total_sum * (total_sum - total_sum)) // 2 # Compute S2 using similar expansion logic but more complex due to three terms cubic_terms = sum(x * x * x for x in A) quadratic_cross_terms = 3 * sum(a * b for i, a in enumerate(A) for b in A[i+1:]) s2 = (cubic_terms + 3 * quadratic_cross_terms + 6 * total_sum * (total_sum - A[0]) * (total_sum - A[-1])) // 6 return s1, s2 ``` This approach leverages algebraic identities to reduce complexity significantly compared to brute force methods which would require nested loops with time complexities of O(n^2) for pairs and O(n^3) for triples[^1]. For practical implementation, especially during competitive programming contests, optimizing these calculations further might involve modular arithmetic when dealing with large numbers to prevent overflow issues. --related questions-- 1. How does modular arithmetic apply to preventing integer overflow in such problems? 2. Can you provide examples of other combinatorial summation problems suitable for practice? 3. What are common pitfalls encountered while solving combination-based algorithm challenges? 4. Are there alternative algorithms or data structures useful for handling multiple element combinations?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值